Vega lite use one data field for the axis and another for the label - svg

In Vega Lite, is it possible to use one field of the data values as the axis value, and another field as the label?
If this is my vega lite spec, then the graph works correctly, but shows the dates on the x-axis. How can I show the day names on the x-axis instead?
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"description": "basic line graph",
"data": {
"values": [
{"date":"2017-08-15", "dayName":"Tue","item":"foo","count":"0"},
{"date":"2017-08-16", "dayName":"Wed","item":"foo","count":"11"},
{"date":"2017-08-17", "dayName":"Thu","item":"foo","count":"7"},
{"date":"2017-08-18", "dayName":"Fri","item":"foo","count":"28"},
{"date":"2017-08-19", "dayName":"Sat","item":"foo","count":"0"},
{"date":"2017-08-20", "dayName":"Sun","item":"foo","count":"0"},
{"date":"2017-08-21", "dayName":"Mon","item":"foo","count":"0"}
]},
"mark": {
"type": "line",
"interpolate": "monotone"
},
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "count", "type": "quantitative"}
}
}
It shows the date field, August 16, August 17 on the x-axis. How can I make it show the dayName field instead? It should show Tue, Wed, and so on.

You can use timeUnit.
{
"$schema": "https://vega.github.io/schema/vega-lite/v2.json",
"description": "basic line graph",
"data": {
"values": [
{"date":"2017-08-15", "dayName":"Tue","item":"foo","count":"0"},
{"date":"2017-08-16", "dayName":"Wed","item":"foo","count":"11"},
{"date":"2017-08-17", "dayName":"Thu","item":"foo","count":"7"},
{"date":"2017-08-18", "dayName":"Fri","item":"foo","count":"28"},
{"date":"2017-08-19", "dayName":"Sat","item":"foo","count":"0"},
{"date":"2017-08-20", "dayName":"Sun","item":"foo","count":"0"},
{"date":"2017-08-21", "dayName":"Mon","item":"foo","count":"0"}
]},
"mark": {
"type": "line",
"interpolate": "monotone"
},
"encoding": {
"x": {
"timeUnit": "day",
"field": "date",
"type": "temporal"
},
"y": {"field": "count", "type": "quantitative"}
}
}
If you want to customize the label format, you can add axis format, as well

Related

Why do groups not respect the parent's padding, except at the top level?

What exactly is the behavior of padding for group marks in Vega? At the top-most level the children groups respect the top-level padding, but this doesn't seem the case for the children's children, they don't respect their parent's padding.
For example, here I would expect to get a rectangle centered in a rectangle centered in another rectangle:
Open the Chart in the Vega Editor
Instead each rectangle seems to be anchored at the origin of the top-level coordinate system.
Note that replacing "padding": {"signal": "level_2_padding"} with "padding": {"value": 0} doesn't seem to have any effect, so I'm not even sure if inner groups can have padding?
How can I best implement nested groups that respect the parent's padding?
There is no padding property on a Group mark. Instead, you can access group properties using Field Values. Something like the following should work.
Editor
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"autosize": "none",
"config": {"group": {"stroke": "black"}},
"signals": [
{"name": "target_height", "value": 400},
{"name": "target_width", "value": 300},
{"name": "level_0_padding", "value": 64},
{"name": "level_1_padding", "update": "1/2 * level_0_padding"},
{"name": "level_2_padding", "update": "1/4 * level_0_padding"},
{"name": "level_0_height", "update": "target_height - 2*level_0_padding"},
{"name": "level_0_width", "update": "target_width - 2*level_0_padding"},
{"name": "level_1_width", "update": "level_0_width - 2*level_1_padding"},
{"name": "level_1_height", "update": "level_0_height - 2*level_1_padding"}
],
"width": {"signal": "level_0_width"},
"height": {"signal": "level_0_height"},
"padding": {"signal": "level_0_padding"},
"marks": [
{
"type": "group",
"signals": [
{
"name": "level_2_width",
"update": "level_1_width - 2*level_2_padding"
},
{
"name": "level_2_height",
"update": "level_1_height - 2*level_2_padding"
}
],
"encode": {
"update": {
"width": {"signal": "level_1_width"},
"height": {"signal": "level_1_height"},
"x": {"signal": "level_0_width-level_1_width - level_1_padding"},
"y": {"signal": "level_0_height-level_1_height - level_1_padding"},
"stroke": {"value": "red"},
"strokeOpacity": {"value": 0.5}
}
},
"marks": [
{
"type": "group",
"encode": {
"update": {
"width": {"signal": "level_2_width"},
"height": {"signal": "level_2_height"},
"x": {
"field": {"group": "width"},
"mult": 0.5,
"offset": {"signal": "-level_2_width/2"}
},
"y": {
"field": {"group": "height"},
"mult": 0.5,
"offset": {"signal": "-level_2_height/2"}
},
"stroke": {"value": "blue"},
"strokeOpacity": {"value": 0.5}
}
}
}
]
}
]
}
I'll accept David's answer, but also post my own to complement David's.
Here's an alternative solution specification, like David's spec it uses the "x" and "y" group properties, but I think it's a bit simpler and closer to what I need: Open the Chart in the Vega Editor
An important point that I have to mention is that using layout prevents x and y from working, that is: groups directly contained in a layout/grid may not be offset using x or y.

Can't get transform_filter to work in Altair

For my teaching notes I am trying to implement this vega-lite example in Altair:
{
"data": {"url": "data/seattle-weather.csv"},
"layer": [{
"params": [{
"name": "brush",
"select": {"type": "interval", "encodings": ["x"]}
}],
"mark": "bar",
"encoding": {
"x": {
"timeUnit": "month",
"field": "date",
"type": "ordinal"
},
"y": {
"aggregate": "mean",
"field": "precipitation",
"type": "quantitative"
},
"opacity": {
"condition": {
"param": "brush", "value": 1
},
"value": 0.7
}
}
}, {
"transform": [{
"filter": {"param": "brush"}
}],
"mark": "rule",
"encoding": {
"y": {
"aggregate": "mean",
"field": "precipitation",
"type": "quantitative"
},
"color": {"value": "firebrick"},
"size": {"value": 3}
}
}]
}
I getting the separate charts (bar and rule to work) was easy, but I run into issues in making mark_rule interactive.
import altair as alt
from vega_datasets import data
df = data.seattle_weather()
selection = alt.selection_interval(encodings=['x'])
base = alt.Chart(df).add_selection(selection)
bar_i = base.mark_bar().encode(
x="month(date):T",
y="mean(precipitation):Q",
opacity=alt.condition(selection, alt.value(1.0), alt.value(0.7)))
rule_i = base.mark_rule().transform_filter(selection).encode(y="mean(precipitation):Q")
(bar_i + rule_i).properties(width=600)
The error reads
Javascript Error: Duplicate signal name: "selector013_scale_trigger"
This usually means there's a typo in your chart specification. See the javascript console for the full traceback.
It looks like the chart you're interested in creating is part of Altair's example gallery: https://altair-viz.github.io/gallery/selection_layer_bar_month.html
import altair as alt
from vega_datasets import data
source = data.seattle_weather()
brush = alt.selection(type='interval', encodings=['x'])
bars = alt.Chart(source).mark_bar().encode(
x='month(date):O',
y='mean(precipitation):Q',
opacity=alt.condition(brush, alt.OpacityValue(1), alt.OpacityValue(0.7)),
).add_selection(
brush
)
line = alt.Chart(source).mark_rule(color='firebrick').encode(
y='mean(precipitation):Q',
size=alt.SizeValue(3)
).transform_filter(
brush
)
bars + line
The error you're seeing comes from the fact that base includes the selection, and both layers are derived from base, so the same selection is declared twice within the single chart.

Microsoft Teams Adaptive Card - Dark Mode Color Issue

I am trying to develope a simple messagaging extension app for Microsoft Teams. With the use of Task Modules I can load a simple Adative Card. Works as designed. The only problem I have with it, is that my Adaptive Card has a color issue withing Microsoft Teams in Dark Mode.
Take a look at the image below. 1 shows a very simple Adaptive Card designed via https://adaptivecards.io/designer/ (preview mode). 2 the very same Adaptive Card but now an actual snippet from Microsoft Teams. As you can see the card below has some color issues which makes the input hard to see.
Here is the code I've used:
public async handleTeamsMessagingExtensionFetchTask(
context: TurnContext,
action: any
): Promise<any> {
const adaptiveCard = CardFactory.adaptiveCard({
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"size": "Medium",
"weight": "Bolder",
"text": "${title}"
},
{
"type": "Input.Text",
"placeholder": "Placeholder text"
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.3"
});
return {
task: {
type: 'continue',
value: {
card: adaptiveCard,
height: 535,
title: '${title}',
url: null,
width: 500
}
}
};
}
There's not much that can be done about the input box itself in this case, but maybe try changing the colour of the label above it, something like this (I've changed some of your property names as well, as they were invalid case - things like "medium" instead of "Medium":
"size": "medium",
"weight": "bolder",
"text": "${title}",
"color": "good"
Color allows the following values:
"default"
"dark"
"light"
"accent"
"good"
"warning"
"attention"
If you nest your Text input into a Container, you are able change the Container's style to provide a coloured background upon which the Text input sits.
It's not necessarily right for your use case, but it could be a workaround of interest
Container Style colour options
{
"type": "Container",
"style": "emphasis",
"bleed": true,
"items": [
{
"type": "TextBlock",
"text": "Request New Ticket",
"wrap": true,
"fontType": "Default",
"style": "heading",
"size": "Large",
"color": "Good",
"weight": "Bolder",
"horizontalAlignment": "Center"
}
]
}

Data is getting embedded via a local json file

I'm trying to plot some data, that data is in a pandas dataframe cdfs:
alt.Chart(cdfs).mark_line().encode(
x = alt.X('latency:Q', scale=alt.Scale(type='log'), axis=alt.Axis(format="", title='Response_time (ms)')),
y = alt.Y('percentile:Q', axis=alt.Axis(format="", title='Cumulative Fraction')),
color='write_size:N',
)
The issue is that when viewing the source of the resultant plot there is just a url to a json file. That json file can't be found and hence the plots are appearing to be blank (no data).
{
"config": {"view": {"continuousWidth": 400, "continuousHeight": 300}},
"data": {
"url": "altair-data-78b044f23db74f7d4408fba9f31b9ea9.json",
"format": {"type": "json"}
},
"mark": "line",
"encoding": {
"color": {"type": "nominal", "field": "write_size"},
"x": {
"type": "quantitative",
"axis": {"format": "", "title": "Response_time (ms)"},
"field": "latency",
"scale": {"type": "log"}
},
"y": {
"type": "quantitative",
"axis": {"format": "", "title": "Cumulative Fraction"},
"field": "percentile"
}
},
"$schema": "https://vega.github.io/schema/vega-lite/v4.8.1.json"
}
This code was previously working (displaying the data on the chart) however I restarted the jupyterlab server its running on between now and then.
Hence I'm wondering why the data is getting embedded via a url rather than directly all of a sudden?
At some point in your session, you must have run
alt.data_transformers.enable('json')
If you want to restore the default data transformer which embeds data directly into the chart, run
alt.data_transformers.enable('default')

Update inner object in arangodb

I have an object stored in arangodb which has additional inner objects, my current use case requires that I update just one of the elements.
Store Object
{
"status": "Active",
"physicalCode": "99999",
"postalCode": "999999",
"tradingCurrency": "USD",
"taxRate": "14",
"priceVatInclusive": "No",
"type": "eCommerce",
"name": "John and Sons inc",
"description": "John and Sons inc",
"createdDate": "2015-05-25T11:04:14+0200",
"modifiedDate": "2015-05-25T11:04:14+0200",
"physicalAddress": "Corner moon and space 9 station",
"postalAddress": "PO Box 44757553",
"physicalCountry": "Mars Sector 9",
"postalCountry": "Mars Sector 9",
"createdBy": "john.doe",
"modifiedBy": "john.doe",
"users": [
{
"id": "577458630580",
"username": "john.doe"
}
],
"products": [
{
"sellingPrice": "95.00",
"inStock": "10",
"name": "School Shirt Green",
"code": "SKITO2939999995",
"warehouseId": "723468998682"
},
{
"sellingPrice": "95.00",
"inStock": "5",
"name": "School Shirt Red",
"code": "SKITO245454949495",
"warehouseId": "723468998682"
},
{
"sellingPrice": "95.00",
"inStock": "10",
"discount": "5%",
"name": "School Shirt Blue",
"code": "SKITO293949495",
"warehouseId": "723468998682"
}
]
}
I want to change just one of the products stock value
{
"sellingPrice": "95.00",
"inStock": "10",
"discount": "5%",
"name": "School Shirt Blue",
"code": "SKITO293949495",
"warehouseId": "723468998682"
}
Like update store product stock less 1 where store id = x, something to this effect
FOR store IN stores
FILTER store._key == "837108415472"
FOR product IN store.products
FILTER product.code == "SKITO293949495"
UPDATE product WITH { inStock: (product.inStock - 1) } IN store.products
Apart from the above possibly it makes sense to store product as a separate document in collection store_products. I believe in NOSQL that is the best approach to reduce document size.
Found answer
here arangodb-aql-update-single-object-in-embedded-array and there
arangodb-aql-update-for-internal-field-of-object
I however believe it is best to maintain separate documents and rather use joins when retrieving. Updates easily

Resources