Is it possible to left-align the row label in a Row Facet? - vega-lite

Is it possible to left-align the row label in a Row Facet?
In this case the row field of "Sub-Category".
For example, ...
Accessories
Appliances
Art
....................................................................................................................................................................................................
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 2126,
"Profit": 476
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 2437,
"Profit": 623
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 3952,
"Profit": 1192
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 2142,
"Profit": 358
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 3751,
"Profit": 1190
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 4849,
"Profit": 1028
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 7589,
"Profit": 2403
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 4962,
"Profit": 1154
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 9727,
"Profit": 2778
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 5032,
"Profit": 909
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 8390,
"Profit": 2181
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 4989,
"Profit": 1380
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 2548,
"Profit": 423
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 3521,
"Profit": 977
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 2474,
"Profit": 308
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 645,
"Profit": -144
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 2578,
"Profit": 692
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 3160,
"Profit": 897
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 1211,
"Profit": 197
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 7105,
"Profit": 1621
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 3088,
"Profit": 427
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 3336,
"Profit": 755
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 6746,
"Profit": 1021
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 6517,
"Profit": 690
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 434,
"Profit": 111
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 247,
"Profit": 67
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 442,
"Profit": 115
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 618,
"Profit": 140
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 640,
"Profit": 177
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 1019,
"Profit": 262
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 867,
"Profit": 251
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 733,
"Profit": 199
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 971,
"Profit": 267
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 642,
"Profit": 123
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 1387,
"Profit": 312
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 862,
"Profit": 199
}
]
},
"spacing": {"row": 2},
"facet": {
"row": {
"field": "Sub-Category",
"type": "nominal",
"header": {
"title": null,
"labelAngle": 0,
"labelPadding": 0,
"titlePadding": -40,
"labelAlign": "left"
}
}
},
"spec": {
"width": 120,
"height": 20,
"view": {"stroke": "transparent"},
"mark": {"type": "area", "interpolate": "natural"},
"encoding": {
"x": {
"field": "MonthendDate",
"type": "temporal",
"title": null,
"timeUnit": "yearmonth",
"axis": {"format": "%b %y", "orient": "top",
}
},
"y": {
"field": "Sales",
"type": "quantitative",
"aggregate": "sum",
"scale": {"zero": true},
"axis": {"title": null, "labels": false, "ticks": false}
}
}
},
"resolve": {"scale": {"y": "shared"}}
}

I think this is currently a bug which you can read more about here: https://github.com/vega/vega-lite/issues/5547. If you edit the Vega spec instead, you can achieve what you want.
Final Image
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"background": "white",
"padding": 5,
"data": [
{
"name": "source_0",
"values": [
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 2126,
"Profit": 476
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 2437,
"Profit": 623
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 3952,
"Profit": 1192
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 2142,
"Profit": 358
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 3751,
"Profit": 1190
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 4849,
"Profit": 1028
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 7589,
"Profit": 2403
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 4962,
"Profit": 1154
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 9727,
"Profit": 2778
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 5032,
"Profit": 909
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 8390,
"Profit": 2181
},
{
"Sub-Category": "Accessories",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 4989,
"Profit": 1380
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 2548,
"Profit": 423
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 3521,
"Profit": 977
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 2474,
"Profit": 308
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 645,
"Profit": -144
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 2578,
"Profit": 692
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 3160,
"Profit": 897
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 1211,
"Profit": 197
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 7105,
"Profit": 1621
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 3088,
"Profit": 427
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 3336,
"Profit": 755
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 6746,
"Profit": 1021
},
{
"Sub-Category": "Appliances",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 6517,
"Profit": 690
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-01-31T00:00:00",
"Sales": 434,
"Profit": 111
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-02-29T00:00:00",
"Sales": 247,
"Profit": 67
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-03-31T00:00:00",
"Sales": 442,
"Profit": 115
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-04-30T00:00:00",
"Sales": 618,
"Profit": 140
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-05-31T00:00:00",
"Sales": 640,
"Profit": 177
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-06-30T00:00:00",
"Sales": 1019,
"Profit": 262
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-07-31T00:00:00",
"Sales": 867,
"Profit": 251
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-08-31T00:00:00",
"Sales": 733,
"Profit": 199
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-09-30T00:00:00",
"Sales": 971,
"Profit": 267
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-10-31T00:00:00",
"Sales": 642,
"Profit": 123
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-11-30T00:00:00",
"Sales": 1387,
"Profit": 312
},
{
"Sub-Category": "Art",
"MonthendDate": "2020-12-31T00:00:00",
"Sales": 862,
"Profit": 199
}
]
},
{
"name": "data_0",
"source": "source_0",
"transform": [
{
"type": "formula",
"expr": "toDate(datum[\"MonthendDate\"])",
"as": "MonthendDate"
},
{
"field": "MonthendDate",
"type": "timeunit",
"units": ["year", "month"],
"as": ["yearmonth_MonthendDate", "yearmonth_MonthendDate_end"]
},
{
"type": "aggregate",
"groupby": ["yearmonth_MonthendDate", "Sub-Category"],
"ops": ["sum"],
"fields": ["Sales"],
"as": ["sum_Sales"]
}
]
},
{
"name": "row_domain",
"source": "data_0",
"transform": [{"type": "aggregate", "groupby": ["Sub-Category"]}]
}
],
"signals": [
{"name": "child_width", "value": 120},
{"name": "child_height", "value": 20}
],
"layout": {
"padding": {"row": 2, "column": 20},
"columns": 1,
"bounds": "full",
"align": "all"
},
"marks": [
{
"name": "row_header",
"type": "group",
"role": "row-header",
"from": {"data": "row_domain"},
"sort": {"field": "datum[\"Sub-Category\"]", "order": "ascending"},
"title": {
"text": {
"signal": "isValid(parent[\"Sub-Category\"]) ? parent[\"Sub-Category\"] : \"\"+parent[\"Sub-Category\"]"
},
"orient": "right",
"style": "guide-label",
"frame": "group",
"baseline": "middle",
"align": "right",
"angle": 0,
"offset": -60
},
"encode": {"update": {"height": {"signal": "child_height"}}},
"axes": [
{
"scale": "y",
"orient": "left",
"grid": false,
"labels": false,
"ticks": false,
"labelOverlap": true,
"tickCount": {"signal": "ceil(child_height/40)"},
"zindex": 0
}
]
},
{
"name": "column_header",
"type": "group",
"role": "column-header",
"encode": {"update": {"width": {"signal": "child_width"}}},
"axes": [
{
"scale": "x",
"orient": "top",
"grid": false,
"format": "%b %y",
"labelFlush": true,
"labelOverlap": true,
"tickCount": {"signal": "ceil(child_width/40)"},
"zindex": 0
}
]
},
{
"name": "cell",
"type": "group",
"style": "cell",
"from": {
"facet": {
"name": "facet",
"data": "data_0",
"groupby": ["Sub-Category"]
}
},
"sort": {"field": ["datum[\"Sub-Category\"]"], "order": ["ascending"]},
"encode": {
"update": {
"width": {"signal": "child_width"},
"height": {"signal": "child_height"},
"stroke": {"value": "transparent"}
}
},
"marks": [
{
"name": "child_marks",
"type": "area",
"style": ["area"],
"sort": {"field": "datum[\"yearmonth_MonthendDate\"]"},
"from": {"data": "facet"},
"encode": {
"update": {
"interpolate": {"value": "natural"},
"orient": {"value": "vertical"},
"fill": {"value": "#4c78a8"},
"description": {
"signal": "\"MonthendDate (year-month): \" + (timeFormat(datum[\"yearmonth_MonthendDate\"], '%b %y')) + \"; Sum of Sales: \" + (format(datum[\"sum_Sales\"], \"\"))"
},
"x": {"scale": "x", "field": "yearmonth_MonthendDate"},
"y": {"scale": "y", "field": "sum_Sales"},
"y2": {"scale": "y", "value": 0},
"defined": {
"signal": "isValid(datum[\"yearmonth_MonthendDate\"]) && isFinite(+datum[\"yearmonth_MonthendDate\"]) && isValid(datum[\"sum_Sales\"]) && isFinite(+datum[\"sum_Sales\"])"
}
}
}
}
],
"axes": [
{
"scale": "x",
"orient": "top",
"gridScale": "y",
"grid": true,
"tickCount": {"signal": "ceil(child_width/40)"},
"domain": false,
"labels": false,
"aria": false,
"maxExtent": 0,
"minExtent": 0,
"ticks": false,
"zindex": 0
},
{
"scale": "y",
"orient": "left",
"gridScale": "x",
"grid": true,
"tickCount": {"signal": "ceil(child_height/40)"},
"domain": false,
"labels": false,
"aria": false,
"maxExtent": 0,
"minExtent": 0,
"ticks": false,
"zindex": 0
}
]
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {"data": "data_0", "field": "yearmonth_MonthendDate"},
"range": [0, {"signal": "child_width"}]
},
{
"name": "y",
"type": "linear",
"domain": {"data": "data_0", "field": "sum_Sales"},
"range": [{"signal": "child_height"}, 0],
"zero": true,
"nice": true
}
],
"config": {"style": {"cell": {"stroke": "transparent"}}}
}

Related

vega-lite dougnut chart with a dropdown is not working as expected. What am I doing wrong?

I have a vega-lite chart that I need a dropdown for and am having trouble getting it to work as expected. It looks to me like by default it is selecting data for the last element in the data [agent 'Tommy'] and the colors are fine for the data that's there. When another agent is selected the colors do not update correctly. null is in the list and that seems to reset the chart back to the correct colors for the last agent again. This is my json in the editor. Any help would be appreciated.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{"agent": "Mabel", "type": "answered less than 20", "value": 9},
{"agent": "Mabel", "type": "answered less than 15", "value": 15},
{"agent": "Mabel", "type": "answered less than 10", "value": 24},
{"agent": "Mabel", "type": "answered less than 5", "value": 11},
{"agent": "Mabel", "type": "answered greater than 20", "value": 4},
{"agent": "Mabel", "type": "abandon system", "value": 0},
{"agent": "Mabel", "type": "abandon agent", "value": 9},
{"agent": "Bart", "type": "answered less than 20", "value": 3},
{"agent": "Bart", "type": "answered less than 15", "value": 1},
{"agent": "Bart", "type": "answered less than 10", "value": 6},
{"agent": "Bart", "type": "answered less than 5", "value": 14},
{"agent": "Bart", "type": "answered greater than 20", "value": 11},
{"agent": "Bart", "type": "abandon system", "value": 0},
{"agent": "Bart", "type": "abandon agent", "value": 8},
{"agent": "Tommy", "type": "answered less than 20", "value": 48},
{"agent": "Tommy", "type": "answered less than 15", "value": 18},
{"agent": "Tommy", "type": "answered less than 10", "value": 11},
{"agent": "Tommy", "type": "answered less than 5", "value": 15},
{"agent": "Tommy", "type": "answered greater than 20", "value": 2},
{"agent": "Tommy", "type": "abandon system", "value": 0},
{"agent": "Tommy", "type": "abandon agent", "value": 11}
]
},
"description": "test",
"height": 200,
"layer": [
{
"encoding": {
"color": {
"condition": {"param": "Agents", "field": "type", "scale": {"scheme": "spectral"}, "type": "nominal"},
"value": "grey"
},
"theta": {"field": "value", "type": "quantitative"},
"tooltip": [
{"field": "type", "type": "nominal"},
{"field": "value", "type": "quantitative"}
]
},
"mark": {"innerRadius": 50, "outerRadius": 100, "type": "arc"},
"params": [
{
"bind": {
"input": "select",
"options": [null, "Mabel", "Bart", "Tommy"]
},
"name": "Agents",
"select": {"fields": ["agent"], "type": "point"}
}
]
},
{
"encoding": {"text": {"field": "total", "type": "nominal"}},
"mark": {
"fontSize": 23,
"fontWeight": "bold",
"tooltip": "Calls answered within 20 seconds",
"type": "text"
}
}
],
"title": "Agent Service Levels",
"width": 200
}
this json worked:
the keys were:
the color condition
the transform
the auto size with the resize set to true to fix the legend after the filter update.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"agent": "Mabel",
"type": "answered less than 20",
"value": 5
},
{
"agent": "Mabel",
"type": "answered less than 15",
"value": 15
},
{
"agent": "Mabel",
"type": "answered less than 10",
"value": 16
},
{
"agent": "Mabel",
"type": "answered less than 5",
"value": 13
},
{
"agent": "Mabel",
"type": "answered greater than 20",
"value": 2
},
{
"agent": "Mabel",
"type": "abandon system",
"value": 0
},
{
"agent": "Mabel",
"type": "abandon agent",
"value": 8
},
{
"agent": "Bart",
"type": "answered less than 20",
"value": 8
},
{
"agent": "Bart",
"type": "answered less than 15",
"value": 28
},
{
"agent": "Bart",
"type": "answered less than 10",
"value": 21
},
{
"agent": "Bart",
"type": "answered less than 5",
"value": 7
},
{
"agent": "Bart",
"type": "answered greater than 20",
"value": 1
},
{
"agent": "Bart",
"type": "abandon system",
"value": 0
},
{
"agent": "Bart",
"type": "abandon agent",
"value": 3
},
{
"agent": "Tommy",
"type": "answered less than 20",
"value": 15
},
{
"agent": "Tommy",
"type": "answered less than 15",
"value": 9
},
{
"agent": "Tommy",
"type": "answered less than 10",
"value": 14
},
{
"agent": "Tommy",
"type": "answered less than 5",
"value": 5
},
{
"agent": "Tommy",
"type": "answered greater than 20",
"value": 12
},
{
"agent": "Tommy",
"type": "abandon system",
"value": 0
},
{
"agent": "Tommy",
"type": "abandon agent",
"value": 10
}
]
},
"description": "test",
"height": 200,
"layer": [
{
"encoding": {
"color": {
"condition": {
"param": "Agents",
"field": "type",
"type": "nominal",
"scale": {
"scheme": "spectral"
}
},
"value": null
},
"opacity": {
"condition": {
"param": "industry",
"value": 1
},
"value": 0.2
},
"theta": {
"field": "value",
"type": "quantitative"
},
"tooltip": [
{
"field": "type",
"type": "nominal"
},
{
"field": "value",
"type": "quantitative"
}
]
},
"mark": {
"innerRadius": 50,
"outerRadius": 100,
"type": "arc"
},
"params": [
{
"bind": {
"input": "select",
"options": [
"{none}",
"Mabel",
"Bart",
"Tommy"
]
},
"name": "Agents",
"select": {
"fields": [
"agent"
],
"type": "point"
}
},
{
"bind": "legend",
"name": "industry",
"select": {
"fields": [
"type"
],
"type": "point"
}
}
],
"transform": [
{
"filter": {
"field": "agent",
"equal": {
"expr": "Agents_agent"
}
}
}
]
},
{
"encoding": {
"text": {
"value": "100%"
}
},
"mark": {
"fontSize": 23,
"fontWeight": "bold",
"tooltip": "Calls answered within 20 seconds",
"type": "text"
}
}
],
"title": "Agent Service Levels",
"width": 300,
"autosize": {
"type": "pad",
"contains": "padding",
"resize": true
}
}

How to filter keys in record_path in pandas json_normalize method?

I have a large json/dict:
{
"vegetarian": false,
"vegan": false,
"glutenFree": false,
"dairyFree": false,
"veryHealthy": false,
"cheap": false,
"veryPopular": false,
"sustainable": false,
"weightWatcherSmartPoints": 14,
"gaps": "no",
"lowFodmap": false,
"aggregateLikes": 1,
"spoonacularScore": 57.0,
"healthScore": 21.0,
"creditsText": "BBC Good Food",
"sourceName": "BBC Good Food",
"pricePerServing": 231.2,
"id": 1089577,
"title": "Hungarian Goulash Stew",
"readyInMinutes": 120,
"servings": 4,
"sourceUrl": "https://www.bbcgoodfood.com/recipes/1107653/hungarian-goulash-stew",
"image": "https://spoonacular.com/recipeImages/1089577-312x231.jpg",
"imageType": "jpg",
"nutrition": {
"nutrients": [
{
"name": "Calories",
"title": "Calories",
"amount": 323.18,
"unit": "kcal",
"percentOfDailyNeeds": 16.16
},
{
"name": "Fat",
"title": "Fat",
"amount": 15.14,
"unit": "g",
"percentOfDailyNeeds": 23.3
},
{
"name": "Saturated Fat",
"title": "Saturated Fat",
"amount": 4.43,
"unit": "g",
"percentOfDailyNeeds": 27.69
},
{
"name": "Carbohydrates",
"title": "Carbohydrates",
"amount": 38.95,
"unit": "g",
"percentOfDailyNeeds": 12.98
},
{
"name": "Net Carbohydrates",
"title": "Net Carbohydrates",
"amount": 34.64,
"unit": "g",
"percentOfDailyNeeds": 12.6
},
{
"name": "Sugar",
"title": "Sugar",
"amount": 11.27,
"unit": "g",
"percentOfDailyNeeds": 12.52
},
{
"name": "Cholesterol",
"title": "Cholesterol",
"amount": 102.67,
"unit": "mg",
"percentOfDailyNeeds": 34.22
},
{
"name": "Sodium",
"title": "Sodium",
"amount": 1864.24,
"unit": "mg",
"percentOfDailyNeeds": 81.05
},
{
"name": "Protein",
"title": "Protein",
"amount": 10.3,
"unit": "g",
"percentOfDailyNeeds": 20.6
},
{
"name": "Vitamin A",
"title": "Vitamin A",
"amount": 3866.5,
"unit": "IU",
"percentOfDailyNeeds": 77.33
},
{
"name": "Vitamin E",
"title": "Vitamin E",
"amount": 3.49,
"unit": "mg",
"percentOfDailyNeeds": 23.3
},
{
"name": "Selenium",
"title": "Selenium",
"amount": 13.41,
"unit": "µg",
"percentOfDailyNeeds": 19.16
},
{
"name": "Manganese",
"title": "Manganese",
"amount": 0.38,
"unit": "mg",
"percentOfDailyNeeds": 18.83
},
{
"name": "Iron",
"title": "Iron",
"amount": 3.19,
"unit": "mg",
"percentOfDailyNeeds": 17.74
},
{
"name": "Vitamin B2",
"title": "Vitamin B2",
"amount": 0.3,
"unit": "mg",
"percentOfDailyNeeds": 17.54
},
{
"name": "Fiber",
"title": "Fiber",
"amount": 4.31,
"unit": "g",
"percentOfDailyNeeds": 17.22
},
{
"name": "Folate",
"title": "Folate",
"amount": 61.04,
"unit": "µg",
"percentOfDailyNeeds": 15.26
},
{
"name": "Vitamin B6",
"title": "Vitamin B6",
"amount": 0.3,
"unit": "mg",
"percentOfDailyNeeds": 14.9
},
{
"name": "Vitamin B1",
"title": "Vitamin B1",
"amount": 0.21,
"unit": "mg",
"percentOfDailyNeeds": 13.72
},
{
"name": "Vitamin K",
"title": "Vitamin K",
"amount": 13.78,
"unit": "µg",
"percentOfDailyNeeds": 13.13
},
{
"name": "Potassium",
"title": "Potassium",
"amount": 407.99,
"unit": "mg",
"percentOfDailyNeeds": 11.66
},
{
"name": "Vitamin C",
"title": "Vitamin C",
"amount": 9.53,
"unit": "mg",
"percentOfDailyNeeds": 11.56
},
{
"name": "Phosphorus",
"title": "Phosphorus",
"amount": 111.88,
"unit": "mg",
"percentOfDailyNeeds": 11.19
},
{
"name": "Vitamin B3",
"title": "Vitamin B3",
"amount": 2.01,
"unit": "mg",
"percentOfDailyNeeds": 10.05
},
{
"name": "Copper",
"title": "Copper",
"amount": 0.15,
"unit": "mg",
"percentOfDailyNeeds": 7.53
},
{
"name": "Magnesium",
"title": "Magnesium",
"amount": 29.73,
"unit": "mg",
"percentOfDailyNeeds": 7.43
},
{
"name": "Vitamin B5",
"title": "Vitamin B5",
"amount": 0.69,
"unit": "mg",
"percentOfDailyNeeds": 6.95
},
{
"name": "Zinc",
"title": "Zinc",
"amount": 0.89,
"unit": "mg",
"percentOfDailyNeeds": 5.93
},
{
"name": "Calcium",
"title": "Calcium",
"amount": 58.6,
"unit": "mg",
"percentOfDailyNeeds": 5.86
},
{
"name": "Vitamin B12",
"title": "Vitamin B12",
"amount": 0.2,
"unit": "µg",
"percentOfDailyNeeds": 3.3
},
{
"name": "Vitamin D",
"title": "Vitamin D",
"amount": 0.46,
"unit": "µg",
"percentOfDailyNeeds": 3.06
}
]
}
I would like to keep the id, readyInMinutes and title keys + nutrition, the issue is that I need the nutrition to be parsed (because it's a list of dicts).
I am trying panda's pd.json_normalize function to do this:
keys = ['id', 'title', 'readyInMinutes']
pd.json_normalize(results[0], meta = keys, record_path=['nutrition',['nutrients']], record_prefix='nutrients.')
But if I need to filter which keys I want inside the record_path? For example only title and amount?
Please instruct how can I configure it.
To parse JSON data you can use JMESPath library.
JMESPath search syntax:
search(<jmespath expr>, <JSON document>)
In your case the JMESPath expression will be this:
{id: id, readyInMinutes:readyInMinutes, title: title, nutrition: {nutrients: nutrition.nutrients[*].{title: title, amount: amount}}}
Output:
{
"id": 1089577,
"readyInMinutes": 120,
"title": "Hungarian Goulash Stew",
"nutrition": {
"nutrients": [
{
"title": "Calories",
"amount": 323.18
},
{
"title": "Fat",
"amount": 15.14
},
{
"title": "Saturated Fat",
"amount": 4.43
},
{
"title": "Carbohydrates",
"amount": 38.95
},
{
"title": "Net Carbohydrates",
"amount": 34.64
},
{
"title": "Sugar",
"amount": 11.27
},
{
"title": "Cholesterol",
"amount": 102.67
},
{
"title": "Sodium",
"amount": 1864.24
},
{
"title": "Protein",
"amount": 10.3
},
{
"title": "Vitamin A",
"amount": 3866.5
},
{
"title": "Vitamin E",
"amount": 3.49
},
{
"title": "Selenium",
"amount": 13.41
},
{
"title": "Manganese",
"amount": 0.38
},
{
"title": "Iron",
"amount": 3.19
},
{
"title": "Vitamin B2",
"amount": 0.3
},
{
"title": "Fiber",
"amount": 4.31
},
{
"title": "Folate",
"amount": 61.04
},
{
"title": "Vitamin B6",
"amount": 0.3
},
{
"title": "Vitamin B1",
"amount": 0.21
},
{
"title": "Vitamin K",
"amount": 13.78
},
{
"title": "Potassium",
"amount": 407.99
},
{
"title": "Vitamin C",
"amount": 9.53
},
{
"title": "Phosphorus",
"amount": 111.88
},
{
"title": "Vitamin B3",
"amount": 2.01
},
{
"title": "Copper",
"amount": 0.15
},
{
"title": "Magnesium",
"amount": 29.73
},
{
"title": "Vitamin B5",
"amount": 0.69
},
{
"title": "Zinc",
"amount": 0.89
},
{
"title": "Calcium",
"amount": 58.6
},
{
"title": "Vitamin B12",
"amount": 0.2
},
{
"title": "Vitamin D",
"amount": 0.46
}
]
}
}

Vega-lite: field appears in the wrong chart?

I'm seeing a strange behavior in Vega Lite that I don't understand.
Take this example chart:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"values": [
{"model": "Sedan", "color": "Red", "sales": 28},
{"model": "Sedan", "color": "Silver", "sales": 17},
{"model": "Sedan", "color": "Black", "sales": 34},
{"model": "Pickup", "color": "Red", "sales": 20},
{"model": "Pickup", "color": "Silver", "sales": 71},
{"model": "Pickup", "color": "Black", "sales": 14},
{"model": "Minivan", "color": "Red", "sales": 52},
{"model": "Minivan", "color": "Silver", "sales": 31},
{"model": "Minivan", "color": "Black", "sales": 45}
]
},
"concat": [{
"mark": "bar",
"encoding": {
"x": {"field": "model"},
"y": {"aggregate": "sum", "field": "sales"}
}
},{
"mark": "arc",
"encoding": {
"color": {"field": "color"},
"theta": {"aggregate": "sum", "field": "sales"}
}
}]
}
The result is straightforward enough:
Now, watch what happens when I generate a new field "flag" in the transform section of the first chart, to highlight a specific bar (Pickups):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"values": [
{"model": "Sedan", "color": "Red", "sales": 28},
{"model": "Sedan", "color": "Silver", "sales": 17},
{"model": "Sedan", "color": "Black", "sales": 34},
{"model": "Pickup", "color": "Red", "sales": 20},
{"model": "Pickup", "color": "Silver", "sales": 71},
{"model": "Pickup", "color": "Black", "sales": 14},
{"model": "Minivan", "color": "Red", "sales": 52},
{"model": "Minivan", "color": "Silver", "sales": 31},
{"model": "Minivan", "color": "Black", "sales": 45}
]
},
"concat": [{
"mark": "bar",
"transform": [
{"calculate": "datum.model == 'Pickup'", "as": "flag"} // <- "flag" defined here
],
"encoding": {
"x": {"field": "model"},
"y": {"aggregate": "sum", "field": "sales"},
"color": {"field": "flag"} // <- and used here
}
},{
"mark": "arc", // <- the second chart
"encoding": { // shouldn't even see
"color": {"field": "color"}, // the new "flag" field
"theta": {"aggregate": "sum", "field": "sales"} //
}
}]
}
The flag works (Pickup bar is highlighted) but even though I defined it in the context of the first chart, it influences the second chart and its legend:
Is this a bug? Did I misunderstand something very basic about how Vega Lite works?
The issue is that in compound charts, Vega-Lite uses shared scales by default (See Scale and Guide Resolution).
If you want your color scales to be independent, you can set
"resolve": {"scale": {"color": "independent"}}
The full spec would look like this (view in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"values": [
{"model": "Sedan", "color": "Red", "sales": 28},
{"model": "Sedan", "color": "Silver", "sales": 17},
{"model": "Sedan", "color": "Black", "sales": 34},
{"model": "Pickup", "color": "Red", "sales": 20},
{"model": "Pickup", "color": "Silver", "sales": 71},
{"model": "Pickup", "color": "Black", "sales": 14},
{"model": "Minivan", "color": "Red", "sales": 52},
{"model": "Minivan", "color": "Silver", "sales": 31},
{"model": "Minivan", "color": "Black", "sales": 45}
]
},
"concat": [
{
"mark": "bar",
"transform": [{"calculate": "datum.model == 'Pickup'", "as": "flag"}],
"encoding": {
"x": {"field": "model"},
"y": {"aggregate": "sum", "field": "sales"},
"color": {"field": "flag"}
}
},
{
"mark": "arc",
"encoding": {
"color": {"field": "color"},
"theta": {"aggregate": "sum", "field": "sales"}
}
}
],
"resolve": {"scale": {"color": "independent"}}
}

Vega-lite: customize axis style based on selection

I'm trying to customize the style of axis labels based on a selection, meaning whether the label is included in a selection or not.
Starting from this demo spec (Open the Chart in the Vega Editor) the selection works as expected, highlighting the selected bar:
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"values": [
{ "model": "Sedan", "sales": 12 },
{ "model": "Coupe", "sales": 10 },
{ "model": "Sports car", "sales": 35 },
{ "model": "Station wagon", "sales": 69 },
{ "model": "Hatchback", "sales": 91 },
{ "model": "Convertible", "sales": 53 },
{ "model": "Sport-utility vehicle", "sales": 14 },
{ "model": "Minivan", "sales": 48 }
]
},
"mark": "bar",
"selection": {
"select_model": { "type": "single", "fields": ["model"] }
},
"encoding": {
"y": { "field": "model" },
"x": { "field": "sales", "type": "quantitative" },
"fillOpacity": {
"value": 0.3,
"condition": { "selection": "select_model", "value": 1 }
}
}
}
But I would like to highlight the axis labels too (and maybe accept clicks on them? I'm not sure if that's possible)
If I try to replace the Y encoding with this:
"y": {
"field": "model",
"axis": {
"labelOpacity": {
"value": 0.3,
"condition": {
"test": { "selection": "select_model" },
"value": 1
}
}
}
}
I get the following error:
Cannot read property 'getSelectionComponent' of null
What am I doing wrong?
The reason your approach did not work is because scale labels are never contained in selections. You can accomplish what you want by explicitly testing if the label is present in the selected values using a vega expression. It might look something like this:
"axis": {
"labelOpacity": {
"value": 0.3,
"condition": {
"test": "indexof(select_model.model || [], datum.value) >= 0",
"value": 1
}
}
}
This is the full result (view in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"values": [
{"model": "Sedan", "sales": 12},
{"model": "Coupe", "sales": 10},
{"model": "Sports car", "sales": 35},
{"model": "Station wagon", "sales": 69},
{"model": "Hatchback", "sales": 91},
{"model": "Convertible", "sales": 53},
{"model": "Sport-utility vehicle", "sales": 14},
{"model": "Minivan", "sales": 48}
]
},
"mark": "bar",
"selection": {
"select_model": {"type": "single", "fields": ["model"], "empty": "none"}
},
"transform": [
{"calculate": "indexof(select_model.model || [], 'Hatchback')", "as": "Val"}
],
"encoding": {
"y": {
"field": "model",
"axis": {
"labelOpacity": {
"value": 0.3,
"condition": {
"test": "indexof(select_model.model || [], datum.value) >= 0",
"value": 1
}
}
}
},
"x": {"field": "sales", "type": "quantitative"},
"fillOpacity": {
"value": 0.3,
"condition": {"selection": "select_model", "value": 1}
}
}
}

How to extract text from json with parent siblings and substrings?

https://bern.korea.ac.kr/pubmed/32818866
$ jq -r '.[] | .denotations | .[] | select(.obj=="drug") | .span | [.begin, .end] | #tsv'
I am able to extract the following info from the above URL using the above jq command.
377 387
562 579
584 602
659 676
681 699
919 936
941 959
1032 1049
1054 1072
But the output that I really need is the following.
The last column is just the substring of text starting from begin+1 to end (suppose the string in text is indexed starting from 1.
I don't know how to extract this info using just jq as it involves taking a parent sibling element and the substring of another parent sibling element. Could anybody show me how to extract the output in this format? Thanks.
32818866 377 387 silica gel
32818866 562 579 7-methoxycoumarin
32818866 584 602 8-prenylkaempferol
32818866 659 676 7-methoxycoumarin
32818866 681 699 8-prenylkaempferol
32818866 919 936 7-methoxycoumarin
32818866 941 959 8-prenylkaempferol
32818866 1032 1049 7-methoxycoumarin
32818866 1054 1072 8-prenylkaempferol
The json txt is here for the completeness of this message.
[
{
"project": "BERN",
"sourcedb": "PubMed",
"sourceid": "32818866",
"text": "Identification of two bitter components in Zanthoxylum bungeanum Maxim. and exploration of their bitter taste mechanism through receptor hTAS2R14. Bitterness is an inherent organoleptic characteristic affecting the flavor of Zanthoxylum bungeanum Maxim. In this study, the vital bitter components of Z. bungeanum were concentrated through solvent extraction, sensory analysis, silica gel chromatography, and thin-layer chromatographic techniques and subsequently identified by UPLC-Q-TOF-MS. Two components with the highest bitterness intensities (BIs), such as 7-methoxycoumarin and 8-prenylkaempferol were selected. The bitter taste perceived thresholds of 7-methoxycoumarin and 8-prenylkaempferol were 0.062 mmol/L and 0.022 mmol/L, respectively. Moreover, the correlation between the contents of the two bitter components and the BIs of Z. bungeanum were proved. The results of siRNA and flow cytometry showed that 7-methoxycoumarin and 8-prenylkaempferol could activate the bitter receptor hTAS2R14. The results concluded that 7-methoxycoumarin and 8-prenylkaempferol contribute to the bitter taste of Z. bungeanum.",
"denotations": [
{
"id": [
"NCBI:txid328401"
],
"span": {
"begin": 43,
"end": 64
},
"obj": "species"
},
{
"id": [
"CUI-less"
],
"span": {
"begin": 128,
"end": 145
},
"obj": "gene"
},
{
"id": [
"NCBI:txid328401"
],
"span": {
"begin": 225,
"end": 246
},
"obj": "species"
},
{
"id": [
"NCBI:txid328401"
],
"span": {
"begin": 300,
"end": 312
},
"obj": "species"
},
{
"id": [
"MESH:D058428",
"BERN:315272203"
],
"span": {
"begin": 377,
"end": 387
},
"obj": "drug"
},
{
"id": [
"CHEBI:5679",
"BERN:4597103"
],
"span": {
"begin": 562,
"end": 579
},
"obj": "drug"
},
{
"id": [
"MESH:C532177",
"BERN:280529003"
],
"span": {
"begin": 584,
"end": 602
},
"obj": "drug"
},
{
"id": [
"CHEBI:5679",
"BERN:4597103"
],
"span": {
"begin": 659,
"end": 676
},
"obj": "drug"
},
{
"id": [
"MESH:C532177",
"BERN:280529003"
],
"span": {
"begin": 681,
"end": 699
},
"obj": "drug"
},
{
"id": [
"NCBI:txid328401"
],
"span": {
"begin": 841,
"end": 853
},
"obj": "species"
},
{
"id": [
"CHEBI:5679",
"BERN:4597103"
],
"span": {
"begin": 919,
"end": 936
},
"obj": "drug"
},
{
"id": [
"MESH:C532177",
"BERN:280529003"
],
"span": {
"begin": 941,
"end": 959
},
"obj": "drug"
},
{
"id": [
"CUI-less"
],
"span": {
"begin": 979,
"end": 994
},
"obj": "gene"
},
{
"id": [
"CUI-less"
],
"span": {
"begin": 995,
"end": 1003
},
"obj": "gene"
},
{
"id": [
"CHEBI:5679",
"BERN:4597103"
],
"span": {
"begin": 1032,
"end": 1049
},
"obj": "drug"
},
{
"id": [
"MESH:C532177",
"BERN:280529003"
],
"span": {
"begin": 1054,
"end": 1072
},
"obj": "drug"
},
{
"id": [
"NCBI:txid328401"
],
"span": {
"begin": 1107,
"end": 1119
},
"obj": "species"
}
],
"timestamp": "Wed Oct 28 21:43:04 +0000 2020",
"logits": {
"disease": [],
"gene": [
[
{
"start": 128,
"end": 145,
"id": "CUI-less"
},
0.7066106796264648
],
[
{
"start": 979,
"end": 994,
"id": "CUI-less"
},
0.9999749660491943
],
[
{
"start": 995,
"end": 1003,
"id": "CUI-less"
},
0.9052715301513672
]
],
"drug": [
[
{
"start": 377,
"end": 387,
"id": "MESH:D058428\tBERN:315272203"
},
0.999982476234436
],
[
{
"start": 562,
"end": 579,
"id": "CHEBI:5679\tBERN:4597103"
},
0.9999980926513672
],
[
{
"start": 584,
"end": 602,
"id": "MESH:C532177\tBERN:280529003"
},
0.9999980926513672
],
[
{
"start": 659,
"end": 676,
"id": "CHEBI:5679\tBERN:4597103"
},
0.9999980926513672
],
[
{
"start": 681,
"end": 699,
"id": "MESH:C532177\tBERN:280529003"
},
0.9999980330467224
],
[
{
"start": 919,
"end": 936,
"id": "CHEBI:5679\tBERN:4597103"
},
0.9999980926513672
],
[
{
"start": 941,
"end": 959,
"id": "MESH:C532177\tBERN:280529003"
},
0.9999980926513672
],
[
{
"start": 1032,
"end": 1049,
"id": "CHEBI:5679\tBERN:4597103"
},
0.9999980926513672
],
[
{
"start": 1054,
"end": 1072,
"id": "MESH:C532177\tBERN:280529003"
},
0.9999980926513672
]
],
"species": [
[
{
"start": 43,
"end": 64,
"id": "NCBI:txid328401"
},
0.9999997615814209
],
[
{
"start": 225,
"end": 246,
"id": "NCBI:txid328401"
},
0.9999998211860657
],
[
{
"start": 300,
"end": 312,
"id": "NCBI:txid328401"
},
0.9999998211860657
],
[
{
"start": 841,
"end": 853,
"id": "NCBI:txid328401"
},
0.9999998211860657
],
[
{
"start": 1107,
"end": 1119,
"id": "NCBI:txid328401"
},
0.9999998211860657
]
]
},
"elapsed_time": {
"tmtool": 0.991,
"ner": 0.453,
"normalization": 0.172,
"total": 1.617
}
}
]
Assuming the first column of the desired output is the "sourceid", we can adapt your solution as follows:
.[]
| .sourceid as $id
| .text as $text
| .denotations[]
| select(.obj=="drug")
| .span
| [$id, .begin, .end, $text[.begin : .end] ]
| #tsv