Facet graph : how to filter Y - array field - vega-lite

As you can see here in the editor, the version axis shows the version of all product, for each products.
On the exemple there is only 2 products, but I am working with an undefined numbers of products, and I donct want to hardcode a Vconcat for each one.
I would like to make Y axis independant between the different facet i.e. display Product1 according to version that he is using, and Product2 the same. I've been trying for 5/10h+ but can't figure it out alone. Any help is welcome

Do you mean like this?
If so, set your scale to independent.
{
"title": {
"text": "Concordance Produit / Projet, réalisé à partir du planning "
},
"data": {
"values": [
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product 1 V1 ",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2023-04-28",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Produit",
"Signification": "MAD",
"Référentiel": "Product 1 V1 ",
"Signification_bis": "START",
"Date_value": "Confirmed",
"Date_Début": "2023-03-31",
"Date_Fin": "2022-07-07"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product1 V2",
"Signification_bis": "MES",
"Date_value": "ToBeConfirmed ",
"Date_Début": "2023-04-28",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Produit",
"Signification": "MAD",
"Référentiel": "Product1 V2",
"Signification_bis": "START",
"Date_value": "Confirmed",
"Date_Début": "2023-05-26",
"Date_Fin": "2022-07-07"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product1 V3",
"Signification_bis": "MES",
"Date_value": "ToBeConfirmed ",
"Date_Début": "2023-04-28",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Produit",
"Signification": "MAD",
"Référentiel": "Product1 V3",
"Signification_bis": "START",
"Date_value": "Confirmed",
"Date_Début": "2023-06-30",
"Date_Fin": "2022-07-07"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product1 V4",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2024-06-28",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Produit",
"Signification": "MAD",
"Référentiel": "Product1 V4",
"Signification_bis": "START",
"Date_value": "Confirmed",
"Date_Début": "2023-11-02",
"Date_Fin": "2022-07-07"
},
{
"Projet": "Project",
"Produit": "Product2",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product2 V1",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2022-07-04",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product2",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product2 V2",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2023-01-31",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product2",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product2 V3",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2023-07-03",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product2",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product2 V4",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2023-08-18",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Projet",
"Signification": "BESOIN",
"Référentiel": "Product1 V5",
"Signification_bis": "MES",
"Date_value": "Confirmed",
"Date_Début": "2023-06-30",
"Date_Fin": "2023-11-15"
},
{
"Projet": "Project",
"Produit": "Product1",
"ID_task": "Produit",
"Signification": "MAD",
"Référentiel": "Product1 V5",
"Signification_bis": "START",
"Date_value": "Confirmed",
"Date_Début": "2023-04-03",
"Date_Fin": "2022-07-07"
}
]
},
"facet": {"row": {"field": "Produit"}},
"autosize": "pad",
"config": {"tick": {"thickness": 20, "bandSize": 500}},
"spec": {
"width": 800,
"height": 90,
"layer": [
{
"layer": [
{
"params": [
{"name": "grid", "select": "interval", "bind": "scales"}
],
"transform": [
{"filter": {"field": "ID_task", "oneOf": ["Produit"]}}
],
"mark": {
"type": "bar",
"opacity": 1,
"cornerRadius": 10,
"fillOpacity": 0.5,
"height": 15
}
}
],
"encoding": {
"x": {
"field": "Date_Début",
"type": "temporal",
"axis": {
"title": null,
"grid": true,
"labelExpr": "[timeFormat(datum.value, '%b'), timeFormat(datum.value, '%m') == '01' ? timeFormat(datum.value, '%Y') : '']",
"gridDash": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": []
},
"value": [2, 2]
},
"tickDash": {
"condition": {
"test": {"field": "value", "timeUnit": "month", "equal": 1},
"value": []
},
"value": [2, 2]
}
}
},
"x2": {"field": "Date_Fin"},
"y": {
"field": "Référentiel",
"type": "nominal",
"axis": {"title": null, "grid": true, "tickBand": "extent"}
}
}
},
{
"transform": [{"calculate": "now()", "as": "now_field"}],
"mark": {"type": "rule", "color": "#FE8389", "size": 1, "opacity": 0.4},
"encoding": {"x": {"field": "now_field", "type": "temporal"}}
},
{
"transform": [{"filter": {"field": "ID_task", "oneOf": ["Projet"]}}],
"mark": {
"type": "point",
"color": "#EC6602",
"size": 150,
"orient": "horizontal",
"opacity": 0.8,
"shape": "triangle-up"
},
"encoding": {
"color": {
"field": "Date_value",
"scale": {"range": ["#EC6602", "#FFB400"]}
},
"x": {"field": "Date_Début", "type": "temporal"},
"y": {"field": "Référentiel", "type": "nominal"}
}
}
]
},
"resolve": {"scale": {"y": "independent"}}
}

Related

Vega bar line chart opacity issue

In Vega Barline chart, I am looking help, when mouseover on Bar chart, line chart should be blur but all bar should be with opacity 1, similar when mouseover on line chart, bar chart should be blur.
In Vega Barline chart, I am looking help, when mouseover on Bar chart, line chart should be blur but all bar should be with opacity 1, similar when mouseover on line chart, bar chart should be blur.
I tried with below JSON
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"background": "transparent",
"width": 600,
"height": 300,
"style": "linear",
"data": [
{ "name": "barlineChart_store" },
{ "name": "barChart_store" },
{ "name": "lineChart_store" },
{
"name": "source_0",
"values": [ {
"year": 2013,
"value": 10
},
{
"year": 2014,
"value": 19
},
{
"year": 2015,
"value": 33
},
{
"year": 2016,
"value": 74
},
{
"year": 2017,
"value": 87
},
{
"year": 2018,
"value": 13
}, {
"year": 2019,
"value": 110
} ,
{
"year": 2020,
"value": 40
},
{
"year": 2021,
"value": 50
},{
"year": 2022,
"value": 49
}]
},
{
"name": "source_2",
"values": [ {
"year": 2013,
"value": 279670000
},
{
"year": 2014,
"value": 1017789660
},
{
"year": 2015,
"value": 4604761843
},
{
"year": 2016,
"value": 1829007526
},
{
"year": 2017,
"value": 21831592682
},
{
"year": 2018,
"value": 9236173024
},{
"year": 2019,
"value": 9848990024
},{
"year": 2020,
"value": 13365764829
},{
"year": 2021,
"value": 27294260073
},{
"year": 2022,
"value": 9982818889
}]
},
{
"name": "data_0",
"source": "source_0",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
{
"type": "stack",
"groupby": ["year_year"],
"field": "value",
"sort": { "field": [], "order": [] },
"as": ["value_start", "value_end"],
"offset": "zero",
},
{
"type": "filter",
"expr": "isValid(datum[\"value\"]) && isFinite(+datum[\"value\"])",
},
],
},
{
"name": "data_1",
"source": "source_2",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
],
},
{
"name": "data_2",
"source": "source_2",
"transform": [
{
"type": "formula",
"expr": "timeParse(datum[\"year\"],'%Y')",
"as": "year",
},
{
"field": "year",
"type": "timeunit",
"units": ["year"],
"as": ["year_year", "year_year_end"],
},
],
},
{
"name": "data_3",
"source": "data_2",
"transform": [
{
"type": "filter",
"expr": "isValid(datum[\"value\"]) && isFinite(+datum[\"value\"])",
},
],
},
],
"marks": [
{
"type": "group",
"name": "concat_0_group",
"signals": [
{
"name": "mouse__move",
"on": [
{
"events": [
{
"source": "scope",
"type": "mouseover",
},
],
"update":
"datum && item().mark.marktype !== \"group\" ? {unit: \"concat_0\", fields: recentTransaction_name, values: [(item().isVoronoi ? datum.datum : datum)[\"value\"]]} : null",
"force": true,
},
{
"events": [{ "source": "view", "type": "mouseout" }],
"update": "null",
},
],
},
{
"name": "recentTransaction_name",
"value": [{ "type": "E", "field": "value" }],
},
{
"name": "updated_barlinechart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"barlineChart_store\", mouse__move, true)",
},
],
},
{
"name": "updated_linechart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"lineChart_store\", mouse__move, true)",
},
],
},
{
"name": "updated_barchart",
"on": [
{
"events": { "signal": "mouse__move" },
"update": "modify(\"barChart_store\", mouse__move, true)",
},
],
},
],
"marks": [
{
"name": "bar",
"type": "rect",
"style": ["rect"],
"from": {"data": "data_0"},
"encode": {
"update": {
"fill": { "value": "#b14891" },
"description": {
"signal": "\"start (year): \" + (timeFormat(datum[\"year_start\"], timeUnitSpecifier([\"year\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"}))) + \"; end (year): \" + (timeFormat(datum[\"year_end\"], timeUnitSpecifier([\"year\"], {\"year-month\":\"%b %Y \",\"year-month-date\":\"%b %d, %Y \"})))"
},
"x": { "scale": "x", "field": "year_year" },
"width": { "scale": "x", "band": 1 },
"y": { "scale": "layer_0_y", "field": "value_end",
},
"y2": { "scale": "layer_0_y", "field": "value_start" },
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
"opacity": [
{
"test":
"(!length(data('barChart_store')) || vlSelectionTest('barChart_store', datum)) ",
"value": 1,
},
{ "value": 0.2 },
],
"fillopacity": [
{
"test":
"(length(data('barChart_store')) || vlSelectionTest('barChart_store', datum)) ",
"value": 1
},
{"value": 0.2}
],
},
"hover": {
"fillOpacity": {"value": 1}
}
}
},
{
"name": "line",
"type": "line",
"style": ["line"],
"from": { "data": "data_1" },
"encode": {
"update": {
"strokeWidth": { "value": 3 },
"stroke": { "value": "#35a4e8" },
"description": {
"signal":
"'year (year): ' + (timeFormat(datum['year_year'], '%Y'))",
},
"x": { "scale": "x", "field": "year_year", "band": 0.5 },
"y": { "scale": "layer_2_y", "field": "value" ,
},
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
"opacity": [
{
"test":
"(!length(data('barlineChart_store')) || vlSelectionTest('barlineChart_store', datum)) ",
"value": 1,
},
{ "value": 0.7 },
],
"hover": {
"fillOpacity": {"value": 1}
}
},
},
},
{
"name": "point",
"type": "symbol",
"style": ["point"],
"from": { "data": "data_1" },
"encode": {
"update": {
"fill": { "value": "#24242d" },
"stroke": { "value": "#35a4e8" },
"strokeWidth": { "value": 3.5 },
"size" : {"value": "100"},
"ariaRoleDescription": { "value": "point" },
"description": {
"signal":
"'year (year): ' + (timeFormat(datum['year_year'], '%Y'))",
},
"opacity": [
{
"test":
"(!length(data('barlineChart_store')) || vlSelectionTest('barlineChart_store', datum)) ",
"value": 1,
},
{ "value": 0.2 },
],
"x": { "scale": "x", "field": "year_year", "band": 0.5 },
"y": { "scale": "layer_2_y", "field": "value" },
"tooltip": {
"signal": "{'Value of Transactions': datum.value}",
},
},
},
}
],
},
],
"scales": [
{
"name": "x",
"type": "band",
"domain": {
"fields": [
{ "data": "data_0", "field": "year_year" },
{ "data": "data_1", "field": "year_year" },
{ "data": "data_2", "field": "year_year" },
],
"sort": true,
},
"range": [0, { "signal": "width" }],
"padding": 0.6,
},
{
"name": "layer_0_y",
"type": "linear",
"domain": { "data": "data_0", "fields": ["value_start", "value_end"] },
"range": [{ "signal": "height" }, 0],
"nice": true,
"zero": true,
},
{
"name": "layer_2_y",
"type": "linear",
"domain": {
"fields": [
{ "data": "data_2", "field": "value" },
],
},
"range": [{ "signal": "height" }, 0],
"nice": true,
"zero": true,
},
{
"name": "color",
"type": "ordinal",
"domain": ["Number of Transactions", "Value of Transactions"],
"range": ["#ca61aa", "#35a4e8"],
},
],
"axes": [
{
"scale": "x",
"orient": "bottom",
"grid": false,
"labelAngle": 0,
"format": "%Y",
"formatType": "time",
"labelBaseline": "top",
"labelFlush": true,
"labelOverlap": true,
"zindex": 0,
"labelPadding":10,
},
{
"scale": "layer_0_y",
"orient": "left",
"grid": true,
"labelOverlap": true,
"tickCount": { "signal": "ceil(height/80)" },
"zindex": 0,
"title":"Value",
"titleColor":"white",
"labelPadding":10,
},
{
"scale": "layer_2_y",
"orient": "right",
"grid": false,
"labelOverlap": true,
"tickCount": { "signal": "ceil(height/80)" },
"format":".2s",
"zindex": 0,
"title":"Amount",
"titleColor":"white",
"labelPadding":10,
},
],
"legends": [{ "labelColor": "#c4c4cd ", "fill": "color", "direction": "horizontal" ,"orient":"bottom",
"encode": {
"labels": {
"name": "category_legend_labels",
"interactive": true
},
"symbols": {
"name": "category_legend_symbols",
"interactive": true
},
"entries": {
"name": "category_legend_entries",
"interactive": true,
"update": {"fill": {"value": "transparent"}}
}
}}],
"config": { "axis": { "labelColor": "white", "title": "" ,"domain": false, "grid": false,"gridColor": "#979797", "ticks": false},"legend": { "columns":{"signal": "3"},"orient": "bottom",
"layout": {"bottom": {"anchor": "middle"}},
"labelColor": "white"}}
}

Vega-Lite: Adding "All" option in select which doesn't filter the chart

I am trying to implement a drop-down select where if the user selects "All" it would simply not filter and show all data. So far, I have added the select options and the labels.
Here is my code (simplified for visibility)
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"config": {
"bar": {
"height": 30,
"tooltip":true
}
},
"width": 1000,
"height": 600,
"background":"#dddddd",
"title":"Top 10 Richest by Industry",
"data": {
"url": "https://raw.githubusercontent.com/edenfrey/FIT3179_Visualisation2_Globe500/main/data/Billionaires_October_13_2022.csv"
},
"params": [
{
"name": "industry_sel",
"value": "Technology",
"bind": {
"input": "select",
"options": [
null,
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"
],
"labels": [
"All",
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"],
"name": "Industry: "
}
}
],
"layer": [
{
"mark": "bar"
}
],
"encoding": {
"y": {"field": "Name", "type": "nominal","sort": {"op": "sum", "field": "Net Worth", "order":"descending"}},
"x": {"field": "Net Worth", "type": "quantitative", "title": "Net Worth in Billions"}
},
"transform": [
{
"filter": {"field": "Industry", "equal": {"expr": "industry_sel"}}
}
]
}
So far, when the user selects "All" it will simply show nothing (because there is no Industry with null as a value. Furthermore, I wish to only add and change things in this code rather than add other files or hacks (This is an assignment. The criteria is quite strict)
Do it with a ternary operator and make sure you enclose null in quotes.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"config": {
"bar": {
"height": 30,
"tooltip":true
}
},
"width": 1000,
"height": 600,
"background":"#dddddd",
"title":"Top 10 Richest by Industry",
"data": {
"url": "https://raw.githubusercontent.com/edenfrey/FIT3179_Visualisation2_Globe500/main/data/Billionaires_October_13_2022.csv"
},
"params": [
{
"name": "industry_sel",
"value": "Technology",
"bind": {
"input": "select",
"options": [
"null",
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"
],
"labels": [
"All",
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"],
"name": "Industry: "
}
}
],
"layer": [
{
"mark": "bar"
}
],
"encoding": {
"y": {"field": "Name", "type": "nominal","sort": {"op": "sum", "field": "Net Worth", "order":"descending"}},
"x": {"field": "Net Worth", "type": "quantitative", "title": "Net Worth in Billions"}
},
"transform": [
{
"filter": "industry_sel=='null'?industry_sel:datum.Industry == industry_sel"
}
]
}
After looking at David's solution and discovering a set back on a functionality that after choosing a specific industry and going back to "All" would not change back, I have come up with a similar solution to David's.
Code is as follows:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"config": {
"bar": {
"height": 30,
"tooltip":true
}
},
"width": 1000,
"height": 600,
"background":"#dddddd",
"title":"Top 10 Richest by Industry",
"data": {
"url": "https://raw.githubusercontent.com/edenfrey/FIT3179_Visualisation2_Globe500/main/data/Billionaires_October_13_2022.csv"
},
"params": [
{
"name": "industry_sel",
"value": "Technology",
"bind": {
"input": "select",
"options": [
"null",
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"
],
"labels": [
"All",
"Technology",
"Industrial",
"Diversified",
"Finance",
"Consumer",
"Retail",
"Food & Beverage",
"Energy",
"Real Estate",
"Health Care",
"Commodities",
"Media & Telecom",
"Entertainment",
"Services"],
"name": "Industry: "
}
}
],
"layer": [
{
"mark": "bar"
}
],
"encoding": {
"y": {"field": "Name", "type": "nominal","sort": {"op": "sum", "field": "Net Worth", "order":"descending"}},
"x": {"field": "Net Worth", "type": "quantitative", "title": "Net Worth in Billions"}
},
"transform": [
{
"window": [{"op": "rank", "as" : "rank"}]
},
{
"filter": "industry_sel=='null'?datum.rank <= 10:datum.Industry == industry_sel"
}
]
}
From my understanding on how it works is that it will show the top 10 of the (sorted) data no matter the industry choice. This code now works. For the full code and context you can check it out here:
https://raw.githubusercontent.com/edenfrey/FIT3179_Visualisation2_Globe500/main/js/Top_10_Billionaires.vg.json

How to change Shape and Color of points in Vega Scatter Plot?

I have a scatter plot generated with contours code in Vega.
Plot looks like
Based on 3rd field, differentiated the points with colour as Blue and Green Dots, but couldn't see the difference very clearly.
Is it possible to Change the Shape and Colour (atleast one) of the points to make the difference more visible
Code
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"title": {
"text": "Outlier Distribution between Duration Vs Age",
"anchor": "middle",
"fontSize": 16,
"frame": "group",
"offset": 4
},
"signals": [
{
"name": "bandwidth", "value": 0.5,
"bind": {"input": "range", "min": -1, "max": 1, "step": 0.1}
}
],
"data": [
{
"name": "source",
"url" : {
"index": "tenant_id.model_training_artefact",
"body": {
"size":10000,
"_source": ["duration", "credit_amount", "asnm", "age", "outlier"]
}
}
"format": {"property": "hits.hits"},
},
{
"name": "density",
"source": "source",
"transform": [
{
"type": "kde2d",
"groupby": ["_source.outlier"],
"size": [{"signal": "width"}, {"signal": "height"}],
"x": {"expr": "scale('x', datum.duration)"},
"y": {"expr": "scale('y', datum.age)"},
"bandwidth": {"signal": "[bandwidth, bandwidth]"}
}
]
},
{
"name": "contours",
"source": "density",
"transform": [
{
"type": "isocontour",
"field": "grid",
"levels": 4
}
]
}
],
"scales": [
{
"name": "x",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"data": "source", "field": "_source.duration"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"round": true,
"nice": true,
"zero": true,
"domain": {"data": "source", "field": "_source.age"},
"range": "height"
},
{
"name": "color",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": "category"
}
],
"axes": [
{
"scale": "x",
"grid": true,
"domain": false,
"orient": "bottom",
"tickCount": 5,
"title": "Duration"
},
{
"scale": "y",
"grid": true,
"domain": false,
"orient": "left",
"titlePadding": 5,
"title": "Age"
}
],
"legends": [
{"stroke": "color", "symbolType": "stroke"}
],
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "source"},
"encode": {
"update": {
"x": {"scale": "x", "field": "_source.duration"},
"y": {"scale": "y", "field": "_source.age"},
"size": {"value": 50},
"fill": {"scale": "color" , "field": "_source.outlier"}
}
}
},
{
"type": "image",
"from": {"data": "density"},
"encode": {
"update": {
"x": {"value": 0},
"y": {"value": 0},
"width": {"signal": "width"},
"height": {"signal": "height"},
"aspect": {"value": false}
}
},
"transform": [
{
"type": "heatmap",
"field": "datum.grid",
"color": {"expr": "scale('color', datum.datum.outlier)"}
}
]
},
{
"type": "path",
"clip": true,
"from": {"data": "contours"},
"encode": {
"enter": {
"strokeWidth": {"value": 1},
"strokeOpacity": {"value": 1},
"stroke": {"scale": "color", "field": "outlier"}
}
},
"transform": [
{ "type": "geopath", "field": "datum.contour" }
]
}
]
}
Try defining scales for mark symbol color, shape and size.
For example, assuming your field outlier has 3 possible values:
"scales": [
...
{
"name": "scale_symbol_color",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": ["red", "orange", "blue"]
},
{
"name": "scale_symbol_shape",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": ["triangle", "square", "circle"]
},
{
"name": "scale_symbol_size",
"type": "ordinal",
"domain": {
"data": "source", "field": "_source.outlier",
"sort": {"order": "descending"}
},
"range": [400, 300, 200]
}
],
...
"marks": [
{
"name": "marks",
"type": "symbol",
"from": {"data": "source"},
"encode": {
"update": {
"x": {"scale": "x", "field": "_source.duration"},
"y": {"scale": "y", "field": "_source.age"},
"size": {"value": 50},
"fill": {"scale": "scale_symbol_color" , "field": "_source.outlier"},
"shape": {"scale": "scale_symbol_shape" , "field": "_source.outlier"},
"size": {"scale": "scale_symbol_size" , "field": "_source.outlier"},
}
}
},
...
Vega docs:
https://vega.github.io/vega/docs/scales/#ordinal
https://vega.github.io/vega/docs/marks/symbol/

Sankey Diagram (Alluvial Diagram) in Vega-lite

Anyone having an idea on how to create Sankey diagrams like those in Vega-lite?
https://observablehq.com/#d3/sankey-diagram
Input would be data like
From | To | Amount
Using the blog post from Yuri Astrakhan, I created the following in Vega.
{
"$schema": "https://vega.github.io/schema/vega/v5.2.json",
"height": 300,
"width": 600,
"data": [
{
"name": "rawData",
"values": [
{"key": {"stk1": "aa", "stk2": "cc"}, "doc_count": 7},
{"key": {"stk1": "aa", "stk2": "bb"}, "doc_count": 4},
{"key": {"stk1": "bb", "stk2": "aa"}, "doc_count": 8},
{"key": {"stk1": "bb", "stk2": "bb"}, "doc_count": 6},
{"key": {"stk1": "bb", "stk2": "cc"}, "doc_count": 3},
{"key": {"stk1": "cc", "stk2": "aa"}, "doc_count": 9}
],
"transform": [
{"type": "formula", "expr": "datum.key.stk1", "as": "stk1"},
{"type": "formula", "expr": "datum.key.stk2", "as": "stk2"},
{"type": "formula", "expr": "datum.doc_count", "as": "size"}
]
},
{
"name": "nodes",
"source": "rawData",
"transform": [
{
"type": "filter",
"expr": "!groupSelector || groupSelector.stk1 == datum.stk1 || groupSelector.stk2 == datum.stk2"
},
{"type": "formula", "expr": "datum.stk1+datum.stk2", "as": "key"},
{"type": "fold", "fields": ["stk1", "stk2"], "as": ["stack", "grpId"]},
{
"type": "formula",
"expr": "datum.stack == 'stk1' ? datum.stk1+' '+datum.stk2 : datum.stk2+' '+datum.stk1",
"as": "sortField"
},
{
"type": "stack",
"groupby": ["stack"],
"sort": {"field": "sortField", "order": "descending"},
"field": "size"
},
{"type": "formula", "expr": "(datum.y0+datum.y1)/2", "as": "yc"}
]
},
{
"name": "groups",
"source": "nodes",
"transform": [
{
"type": "aggregate",
"groupby": ["stack", "grpId"],
"fields": ["size"],
"ops": ["sum"],
"as": ["total"]
},
{
"type": "stack",
"groupby": ["stack"],
"sort": {"field": "grpId", "order": "descending"},
"field": "total"
},
{"type": "formula", "expr": "scale('y', datum.y0)", "as": "scaledY0"},
{"type": "formula", "expr": "scale('y', datum.y1)", "as": "scaledY1"},
{
"type": "formula",
"expr": "datum.stack == 'stk1'",
"as": "rightLabel"
},
{
"type": "formula",
"expr": "datum.total/domain('y')[1]",
"as": "percentage"
}
]
},
{
"name": "destinationNodes",
"source": "nodes",
"transform": [{"type": "filter", "expr": "datum.stack == 'stk2'"}]
},
{
"name": "edges",
"source": "nodes",
"transform": [
{"type": "filter", "expr": "datum.stack == 'stk1'"},
{
"type": "lookup",
"from": "destinationNodes",
"key": "key",
"fields": ["key"],
"as": ["target"]
},
{
"type": "linkpath",
"orient": "horizontal",
"shape": "diagonal",
"sourceY": {"expr": "scale('y', datum.yc)"},
"sourceX": {"expr": "scale('x', 'stk1') + bandwidth('x')"},
"targetY": {"expr": "scale('y', datum.target.yc)"},
"targetX": {"expr": "scale('x', 'stk2')"}
},
{
"type": "formula",
"expr": "range('y')[0]-scale('y', datum.size)",
"as": "strokeWidth"
},
{
"type": "formula",
"expr": "datum.size/domain('y')[1]",
"as": "percentage"
}
]
}
],
"scales": [
{
"name": "x",
"type": "band",
"range": "width",
"domain": ["stk1", "stk2"],
"paddingOuter": 0.05,
"paddingInner": 0.95
},
{
"name": "y",
"type": "linear",
"range": "height",
"domain": {"data": "nodes", "field": "y1"}
},
{
"name": "color",
"type": "ordinal",
"range": "category",
"domain": {"data": "rawData", "field": "stk1"}
},
{
"name": "stackNames",
"type": "ordinal",
"range": ["Source", "Destination"],
"domain": ["stk1", "stk2"]
}
],
"axes": [
{
"orient": "bottom",
"scale": "x",
"encode": {
"labels": {
"update": {"text": {"scale": "stackNames", "field": "value"}}
}
}
},
{"orient": "left", "scale": "y"}
],
"marks": [
{
"type": "path",
"name": "edgeMark",
"from": {"data": "edges"},
"clip": true,
"encode": {
"update": {
"stroke": [
{
"test": "groupSelector && groupSelector.stack=='stk1'",
"scale": "color",
"field": "stk2"
},
{"scale": "color", "field": "stk1"}
],
"strokeWidth": {"field": "strokeWidth"},
"path": {"field": "path"},
"strokeOpacity": {
"signal": "!groupSelector && (groupHover.stk1 == datum.stk1 || groupHover.stk2 == datum.stk2) ? 0.9 : 0.3"
},
"zindex": {
"signal": "!groupSelector && (groupHover.stk1 == datum.stk1 || groupHover.stk2 == datum.stk2) ? 1 : 0"
},
"tooltip": {
"signal": "datum.stk1 + ' → ' + datum.stk2 + ' ' + format(datum.size, ',.0f') + ' (' + format(datum.percentage, '.1%') + ')'"
}
},
"hover": {"strokeOpacity": {"value": 1}}
}
},
{
"type": "rect",
"name": "groupMark",
"from": {"data": "groups"},
"encode": {
"enter": {
"fill": {"scale": "color", "field": "grpId"},
"width": {"scale": "x", "band": 1}
},
"update": {
"x": {"scale": "x", "field": "stack"},
"y": {"field": "scaledY0"},
"y2": {"field": "scaledY1"},
"fillOpacity": {"value": 0.6},
"tooltip": {
"signal": "datum.grpId + ' ' + format(datum.total, ',.0f') + ' (' + format(datum.percentage, '.1%') + ')'"
}
},
"hover": {"fillOpacity": {"value": 1}}
}
},
{
"type": "text",
"from": {"data": "groups"},
"interactive": false,
"encode": {
"update": {
"x": {
"signal": "scale('x', datum.stack) + (datum.rightLabel ? bandwidth('x') + 8 : -8)"
},
"yc": {"signal": "(datum.scaledY0 + datum.scaledY1)/2"},
"align": {"signal": "datum.rightLabel ? 'left' : 'right'"},
"baseline": {"value": "middle"},
"fontWeight": {"value": "bold"},
"text": {
"signal": "abs(datum.scaledY0-datum.scaledY1) > 13 ? datum.grpId : ''"
}
}
}
},
{
"type": "group",
"data": [
{
"name": "dataForShowAll",
"values": [{}],
"transform": [{"type": "filter", "expr": "groupSelector"}]
}
],
"encode": {
"enter": {
"xc": {"signal": "width/2"},
"y": {"value": 30},
"width": {"value": 80},
"height": {"value": 30}
}
},
"marks": [
{
"type": "group",
"name": "groupReset",
"from": {"data": "dataForShowAll"},
"encode": {
"enter": {
"cornerRadius": {"value": 6},
"fill": {"value": "#f5f5f5"},
"stroke": {"value": "#c1c1c1"},
"strokeWidth": {"value": 2},
"height": {"field": {"group": "height"}},
"width": {"field": {"group": "width"}}
},
"update": {"opacity": {"value": 1}},
"hover": {"opacity": {"value": 0.7}}
},
"marks": [
{
"type": "text",
"interactive": false,
"encode": {
"enter": {
"xc": {"field": {"group": "width"}, "mult": 0.5},
"yc": {
"field": {"group": "height"},
"mult": 0.5,
"offset": 2
},
"align": {"value": "center"},
"baseline": {"value": "middle"},
"fontWeight": {"value": "bold"},
"text": {"value": "Show All"}
}
}
}
]
}
]
},
{
"type": "rect",
"from": {"data": "nodes"},
"encode": {
"enter": {
"stroke": {"value": "#000"},
"strokeWidth": {"value": 2},
"width": {"scale": "x", "band": 1},
"x": {"scale": "x", "field": "stack"},
"y": {"field": "y0", "scale": "y"},
"y2": {"field": "y1", "scale": "y"}
}
}
}
],
"signals": [
{
"name": "groupHover",
"value": {},
"on": [
{
"events": "#groupMark:mouseover",
"update": "{stk1:datum.stack=='stk1' && datum.grpId, stk2:datum.stack=='stk2' && datum.grpId}"
},
{"events": "mouseout", "update": "{}"}
]
},
{
"name": "groupSelector",
"value": false,
"on": [
{
"events": "#groupMark:click!",
"update": "{stack:datum.stack, stk1:datum.stack=='stk1' && datum.grpId, stk2:datum.stack=='stk2' && datum.grpId}"
},
{
"events": [
{"type": "click", "markname": "groupReset"},
{"type": "dblclick"}
],
"update": "false"
}
]
}
]
}
It's a little bit dated, but this blog post shows how to do this kind of 'Sankey' diagram within Kibana using the 'Vega' visualisations.
https://www.elastic.co/blog/sankey-visualization-with-vega-in-kibana
I've played with it a bit a few years ago; it's possible certainly, and rewarding, but that complexity does come at a cost.

How to get a json key that contains a specific string with jq?

I have a json data like this:
{
"success": true,
"module": {
"endpoint": {
"mode": "pc",
"protocolVersion": "2.0"
},
"reload": true,
"data": {
"leftContainer_CL": {
"id": "CL",
"tag": "leftContainer",
"fields": {
"css": {
"floatPosition": "left",
"width": "788px"
},
"tag": "leftContainer"
},
"type": "container"
},
"container_C": {
"id": "C",
"tag": "container",
"fields": {
"css": {
"marginTop": "12px"
},
"tag": "container"
},
"type": "container"
},
"delivery_dfdaf8a8a": {
"id": "dfdaf8a8a",
"tag": "delivery",
"fields": {
"selectPos": "right",
"deliveryBy": {
"text": "Disediakan oleh",
"poster": "ALL ITEM STORE"
},
"options": [
{
"highlight": false,
"deliveryId": "STANDARD",
"bgColor": "#fafafa",
"price": "Rp18.900",
"disable": false,
"reachTime": "Dapatkan pada\n 3-4 Apr 2018",
"liveUp": false,
"selected": true
}
],
"style": "bar"
},
"type": "biz"
},
"rightContainer_CR": {
"id": "CR",
"tag": "rightContainer",
"fields": {
"css": {
"floatPosition": "right",
"width": "388px"
},
"tag": "rightContainer"
},
"type": "container"
},
"delivery_d43597338a": {
"id": "d43597338a",
"tag": "delivery",
"fields": {
"selectPos": "right",
"deliveryBy": {
"text": "Disediakan oleh",
"poster": "incredible accessories hp"
},
"options": [
{
"highlight": false,
"deliveryId": "STANDARD",
"bgColor": "#fafafa",
"price": "Rp37.800",
"disable": false,
"reachTime": "Dapatkan pada\n 3-4 Apr 2018",
"liveUp": false,
"selected": true
}
],
"style": "bar"
},
"type": "biz"
},
"orderSummary_6": {
"id": "6",
"tag": "orderSummary",
"fields": {
"isOpen": "false",
"summarys": [
{
"tail": "(3 barang)",
"title": "Subtotal",
"value": "Rp23.557"
},
{
"title": "Biaya pengiriman",
"value": "Rp56.700"
}
],
"title": "Ringkasan Pesanan\r\n"
},
"type": "biz"
},
"root_0": {
"id": "0",
"tag": "root",
"fields": {
"count": 3,
"title": "Troli belanja Saya"
},
"type": "root"
},
"item_i77997d6b": {
"id": "i77997d6b",
"tag": "item",
"fields": {
"img": "https://id-live.slatic.net/original/08c1396908dc240625751b09decb4211.jpg",
"quantity": {
"qtyPrefix": "Kuantitas",
"min": 1,
"autoOptions": false,
"quantity": 1,
"max": 5,
"editable": true,
"showIncrDecr": true,
"showOptions": false,
"step": 1
},
"sellerName": "ALL ITEM STORE",
"title": "Case Slim Black Matte Xiaomi Redmi 4A Softcase Black",
"stockTip": {},
"valid": true,
"itemId": "143800088",
"operations": [
"wishlist",
"delete"
],
"sellerId": "100124080",
"price": {
"price": 6000,
"currentPrice": "Rp6.000",
"originPrice": "Rp30.000",
"promotionRatio": "-80%"
},
"restriction": false,
"isGift": false,
"sku": {
"skuText": "Softcase, Hitam",
"productVariant": "SO908ELAAVYY4AANID-72544754",
"brandId": "17818",
"skuId": "157608391"
},
"itemUrl": "https://www.lazada.co.id/products/i143800088-s157608391.html?urlFlag=true&mp=1",
"cartItemId": 2006547819
},
"type": "biz"
},
"location_2": {
"id": "2",
"tag": "location",
"fields": {
"buttonText": "GANTI\r\n",
"editable": true,
"postCode": "",
"style": "casAddress",
"label": "Lokasi",
"title": "Jawa Tengah,Kab. Boyolali,Ampel",
"addressId": "R2388357-R80010396-R80015219"
},
"type": "biz"
},
"voucherInput_7": {
"id": "7",
"tag": "voucherInput",
"fields": {
"buttonText": "GUNAKAN",
"placeHolder": "Masukkan Kode Voucher",
"status": "default"
},
"type": "biz",
"validate": {
"value": [
{
"msg": "Maaf, voucher ini tidak dapat digunakan. Silahkan periksa jika ada kesalahan penulisan",
"regex": "^$|^[ ]{0,5}[A-Za-z0-9~!##%&*()_+?<>{}|-]{1,100}[ ]{0,5}$"
}
]
}
},
"shop_43597338a_s2c": {
"id": "43597338a_s2c",
"tag": "shop",
"fields": {
"badges": [],
"link": "//www.lazada.co.id/shop/incredible-accessories-hp",
"name": "incredible accessories hp"
},
"type": "biz"
},
"item_i7799f86e": {
"id": "i7799f86e",
"tag": "item",
"fields": {
"img": "http://id-live-02.slatic.net/p/2/case-anti-shock-anti-crack-elegant-softcase-for-xiaomi-redmi-5a-white-clear-free-tempered-glass-1273-94487227-9f8ddff53bde3f8de9eb514ba2172361-catalog.jpg",
"quantity": {
"qtyPrefix": "Kuantitas",
"min": 1,
"autoOptions": false,
"quantity": 1,
"max": 5,
"editable": true,
"showIncrDecr": true,
"showOptions": false,
"step": 1
},
"sellerName": "incredible accessories hp",
"title": "Case Anti Shock / Anti Crack Elegant Softcase for Xiaomi Redmi 5A - White Clear + Free Tempered Glass",
"stockTip": {},
"valid": true,
"itemId": "160714927",
"operations": [
"wishlist",
"delete"
],
"sellerId": "53631",
"price": {
"price": 13580,
"currentPrice": "Rp13.580",
"originPrice": "Rp25.000",
"promotionRatio": "-46%"
},
"restriction": false,
"isGift": false,
"sku": {
"skuText": "Softcase, Bening",
"productVariant": "SO908ELAB716EPANID-97510528",
"brandId": "17818",
"skuId": "183461134"
},
"itemUrl": "https://www.lazada.co.id/products/i160714927-s183461134.html?urlFlag=true&mp=1",
"cartItemId": 2006579310
},
"type": "biz"
},
"package_p43597338a": {
"id": "p43597338a",
"tag": "package",
"fields": {},
"type": "biz"
},
"listHeader_H": {
"id": "H",
"tag": "listHeader",
"fields": {
"middle": "HARGA",
"left": "3 barang",
"right": "KUANTITAS"
},
"type": "biz"
},
"delivery_3": {
"id": "3",
"tag": "delivery",
"fields": {
"selectPos": "left",
"options": [
{
"highlight": false,
"deliveryId": "STANDARD",
"bgColor": "#fafafa",
"price": "Rp56.700",
"disable": false,
"icon": "https://laz-img-cdn.alicdn.com/tfs/TB1UpyCpfDH8KJjy1XcXXcpdXXa-72-72.png",
"name": "Standar",
"reachTime": "Dapatkan pada\n 3-4 Apr 2018",
"liveUp": false,
"selected": true
}
],
"style": "card",
"title": "Pengiriman yang dipilih"
},
"type": "biz"
},
"orderTotal_8": {
"id": "8",
"tag": "orderTotal",
"fields": {
"button": {
"enable": true,
"text": "LANJUTKAN KE PEMBAYARAN",
"clicked": false
},
"payment": {
"taxTip": "Termasuk PPN, jika berlaku",
"pay": "Rp80.257",
"title": "Total"
}
},
"type": "biz"
},
"shop_fdaf8a8a_s23f9": {
"id": "fdaf8a8a_s23f9",
"tag": "shop",
"fields": {
"badges": [],
"link": "//www.lazada.co.id/shop/all-item-store",
"name": "ALL ITEM STORE"
},
"type": "biz"
},
"floatTips_4": {
"id": "4",
"tag": "floatTips",
"fields": {
"tips": []
},
"type": "biz"
},
"item_i7790e0f9": {
"id": "i7790e0f9",
"tag": "item",
"fields": {
"img": "http://id-live-02.slatic.net/p/2/case-anti-shock-anti-crack-elegant-softcase-for-xiaomi-redmi-note4x-white-clear-8431-85175402-0bec01e88741744ae5461c4b3a4ae160-catalog.jpg",
"quantity": {
"qtyPrefix": "Kuantitas",
"min": 1,
"autoOptions": false,
"quantity": 1,
"max": 5,
"editable": true,
"showIncrDecr": true,
"showOptions": false,
"step": 1
},
"sellerName": "incredible accessories hp",
"title": "Case Anti Shock / Anti Crack Elegant Softcase for Xiaomi Redmi Note 4x - White Clear",
"stockTip": {},
"valid": true,
"itemId": "108849535",
"operations": [
"wishlist",
"delete"
],
"sellerId": "53631",
"price": {
"price": 3977,
"currentPrice": "Rp3.977",
"originPrice": "Rp15.000",
"promotionRatio": "-73%"
},
"restriction": false,
"isGift": false,
"sku": {
"skuText": "Sarung, Bening",
"productVariant": "CA529ELAAC6GUEANID-27304198",
"brandId": "10464",
"skuId": "110628148"
},
"itemUrl": "https://www.lazada.co.id/products/i108849535-s110628148.html?urlFlag=true&mp=1",
"cartItemId": 2005983481
},
"type": "biz"
},
"package_pfdaf8a8a": {
"id": "pfdaf8a8a",
"tag": "package",
"fields": {},
"type": "biz"
}
},
"hierarchy": {
"component": [
"container",
"delivery",
"item",
"shop",
"package",
"listHeader",
"orderSummary",
"leftContainer",
"orderTotal",
"floatTips",
"root",
"location",
"rightContainer",
"voucherInput"
],
"root": "root_0",
"structure": {
"package_p43597338a": [
"delivery_d43597338a",
"shop_43597338a_s2c",
"item_i7799f86e",
"item_i7790e0f9"
],
"leftContainer_CL": [
"delivery_3",
"listHeader_H",
"package_pfdaf8a8a",
"package_p43597338a"
],
"container_C": [
"leftContainer_CL",
"rightContainer_CR"
],
"rightContainer_CR": [
"location_2",
"orderSummary_6"
],
"orderSummary_6": [
"voucherInput_7",
"orderTotal_8"
],
"root_0": [
"container_C",
"floatTips_4"
],
"package_pfdaf8a8a": [
"delivery_dfdaf8a8a",
"shop_fdaf8a8a_s23f9",
"item_i77997d6b"
]
}
},
"linkage": {
"input": [],
"request": [
"voucherInput_7",
"item_i7799f86e",
"delivery_3",
"orderTotal_8",
"item_i7790e0f9",
"location_2",
"item_i77997d6b"
],
"common": {
"compress": true,
"queryParams": "^^$$1afe141216814f45e9fc6dba84d4863d{$_$}H4sIAAAAAAAAAFWU247bRgyGXyXQ9caYGXJOe5fkJmmLot3de4Ez5OwKlSVBklMkQd69lJsNHBgwZIHfz9NPf+t2Wc/DRGN3/61bRtrbvJ67+26p3V230LPoc6V1777fdROd5XGh+vpu05DLJuu7bRuep0OgjrRtf2rYETGfTyN9JabTNfh0nlnG02Xc13k6LbTSeTv9fZH1y1/XZxVbZWJZ3w9ff7xRxXGutA/z9DTs46H6G/1Lb55keqaXu9+pnN68n7/MI43D3bvzIqOKEPMq2/aJNfrBQUrg49uHZIw1kMP/T97ZfPQ3b/sHrUoju+/aoJa8zJNM+/aoDdF+WeXa1TztNEyy9h800jUoDoPFWnMIVHwCMMiWCJ2zgVRX+xw+a2M9aHyMsbpqwcUChTgxeMZqbWzkJXl7G88IPkeARApKMCYQeJNYojCEVPTboMcCmOIvibgxtURXLrRaKGKrWdhHMslkE1ss2TjnCA+ujTPtT8Oy9XgkilVQsgEX2AXJgQ3UZCNb1yKEY1LDLud+iDEbMS0rYwAzx+KbE6JmcgCbs02YJShhyi2TI4eiTAHr0ROiZS0mOteYW9JChZwR+CVPbikce2Ev4HJiJmuab6TJIApIkZo4JFZmlKZb/LmiP66jqzVlEhe5GJEUs/XNk6csxYacDmrY9o9C6rf+oxJAHqAkJMc69RbZu+yBQKxFqTEcxA8r9u5wgagLRISDNuECYjAFk3NYUnU+Htczryr+eDmfSRcUlNEukSyVmqLXeNG9NnWF16RBV95emad5p7FPx5QNGnSUpHDUllsyGINQUKSp78L1Rus/eqb9cmsdgGp1vmpLcKjD1JsNTUGdqmu6olvuxjmlpaa7KV6wtkqU1UimOXA6gIjXk1mH55fbaT8olhJJMhFrrlwxRwuAmK00ELD6+8Dmee9Ndz9dxvGu217mpf9Zb7+5qirZ1YoYOXJlWw1r1Zz1w7kAxKvKlXutVzG4WlFvGUyKxkhB9RNL9ibmmoGTnkJFBT/Pl/oi66dpuex9VMa65LRQ0fRWnDjSZDogFZJkkYL+HfwHDyba3BsFAAA=",
"submitParams": "^^$$f7898231e0216a924bcaa64d213a61ba{$_$}H4sIAAAAAAAAADXMQQrDMAwEwL/oHPSA3PqBUsgLto4bDJJtJPvS4L/XCfS2uwx7UoumKUNoPakK2qeY0ko10EIVR5w5wBqNhTI0bhXhv/kk3aM93NORr4MgcH9OdomiLPhiB9+YtexRuEuzkrnCoM5bf2tqr7vQGD8eVpdVjwAAAA=="
},
"signature": "89dffd9ca23307e603556a4c896e4c56"
}
}
}
With jq I can do this:
[me#linux]$ cat /tmp/json | jq '.module | .data | keys'
[
"container_C",
"delivery_3",
"delivery_d43597338a",
"delivery_dfdaf8a8a",
"floatTips_4",
"item_i7790e0f9",
"item_i77997d6b",
"item_i7799f86e",
"leftContainer_CL",
"listHeader_H",
"location_2",
"orderSummary_6",
"orderTotal_8",
"package_p43597338a",
"package_pfdaf8a8a",
"rightContainer_CR",
"root_0",
"shop_43597338a_s2c",
"shop_fdaf8a8a_s23f9",
"voucherInput_7"
]
I need to get orderTotal_8 but please note that the number 8 is always changing, so it can be orderTotal_10 or orderTotal_3 etc... How can I get this key with pure jq command if possible, without the help of grep / awk ? So the result should be like this orderTotal_8
If you want to form a subarray of items satisfying some condition, just add map(select( CONDITION )) to the pipeline, e.g.
.module | .data | keys | map(select(test("^orderTotal_")))
If you just want a stream of the items matching the condition, then you could first form the stream, and then make the selection:
.module | .data | keys[] | select(test("^orderTotal_"))
For efficiency and other reasons, you might want to consider using keys_unsorted instead of keys.