Forum Discussion
Trelli/multiple scatter deneb
- 3 years ago
Hey Anonymous. Here's my implementation of the SPLOM (scatterplot matrix). Your dataset will need to be flattened and the structure will consist of the following 4 fields:
- Index - a sequential integer identifier for the row
- Observation - The idenitifying name for each dot in the matrix
- Attribute - The variable that will show up on the x and y axes
- Value - The value for the attribute for the given observation
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "params": [{"name": "observation", "expr": "toString(brush['Observation'])"}], "data": { "name": "dataset", "url": "https://raw.githubusercontent.com/Giammaria/PublicFiles/master/pbi/pbi_community_help/20230309_trellis_scatter/data/mtcars_unpivoted.tsv", "format": {"parse": {"Index": "number", "Value": "number"}} }, "transform": [ {"joinaggregate": [{"op": "count", "as": "total_observation_count"}]}, { "calculate": "sequence(1,datum['total_observation_count']+1,1)", "as": "index_2" }, { "calculate": "split(replace(replace(join(datum['index_2'], ','), toString(datum['Index']), ''), ',,', ','), ',')", "as": "index_2" }, {"flatten": ["index_2"], "as": ["index_2"]}, {"filter": "datum['index_2']"}, {"calculate": "+datum['index_2']", "as": "index_2"}, { "lookup": "index_2", "from": { "data": {"name": "dataset"}, "key": "index", "fields": ["Attribute", "Value"] }, "as": ["attribute_2", "value_2"] }, { "calculate": "data('dataset')[datum['index_2']-1]", "as": "row_to_compare" }, {"filter": "datum['Observation']===datum['row_to_compare']['Observation']"}, {"calculate": "datum['row_to_compare']['Attribute']", "as": "attribute_2"}, {"calculate": "datum['row_to_compare']['Value']", "as": "value_2"}, { "calculate": "[datum['Attribute'], datum['attribute_2']]", "as": "variables" }, { "window": [{"op": "distinct", "field": "variables", "as": "facet_count"}], "frame": [null, null], "sort": [{"field": "facet_index", "order": "ascending"}] }, { "window": [ {"op": "dense_rank", "field": "variables", "as": "facet_index"} ], "sort": [{"field": "variables", "order": "ascending"}], "frame": [null, null] }, {"calculate": "floor(sqrt(datum['facet_count']))", "as": "row_count"}, { "calculate": "ceil(datum['facet_count']/datum['row_count'])", "as": "column_count" }, { "calculate": "datum['facet_index']%datum['column_count'] === 0 ? datum['column_count'] : datum['facet_index']%datum['column_count']", "as": "column" }, { "window": [{"op": "dense_rank", "as": "row"}], "groupby": ["column"], "frame": [null, 1], "sort": [{"field": "facet_index", "order": "ascending"}] }, { "window": [{"op": "row_number", "as": "facet_data_index"}], "groupby": ["facet_index"], "frame": [null, null] }, { "calculate": "datum['Attribute']+': '+toString(datum['Value'])", "as": "tooltipX" }, { "calculate": "datum['attribute_2']+': '+toString(datum['value_2'])", "as": "tooltipY" } ], "facet": { "row": {"field": "row", "title": null, "header": null, "type": "ordinal"}, "column": { "field": "column", "type": "ordinal", "title": null, "header": null } }, "spec": { "width": 150, "height": 150, "layer": [ { "name": "splom", "params": [ { "name": "brush", "select": { "type": "point", "on": "mouseover", "encodings": ["color"], "nearest": true, "clear": { "type": "mouseout" } } } ], "mark": {"type": "point", "filled": true}, "encoding": { "x": { "field": "Value", "type": "quantitative", "axis": {"title": null} }, "y": {"field": "value_2", "type": "quantitative", "title": null}, "color": { "condition": { "test": "observation===datum['Observation']", "field": "Observation", "type": "nominal", "legend": null }, "value": "steelblue" }, "size": { "condition": { "test": "observation===datum['Observation']", "value": 400 }, "value": 40 }, "tooltip": [ {"title": "Observation", "field": "Observation"}, {"title": "x", "field": "tooltipX"}, {"title": "y", "field": "tooltipY"} ] } }, { "name": "x-title", "transform": [{"filter": "datum['facet_data_index']===1"}], "mark": { "type": "text", "y": {"expr": "child_height"}, "yOffset": 25, "fontSize": 14 }, "encoding": {"text": {"field": "Attribute"}} }, { "name": "y-title", "transform": [{"filter": "datum['facet_data_index']===1"}], "mark": { "type": "text", "align": "center", "angle": 270, "x": {"expr": "0"}, "xOffset": -30, "fontSize": 14 }, "encoding": {"text": {"field": "attribute_2"}} } ] }, "resolve": { "axis": {"x": "independent", "y": "independent"}, "scale": {"x": "independent", "y": "independent"} }, "config": {"range": {"category": ["orange"]}} }​ - 3 years ago
Hey Jim. This is far from an idea solution but it's as close as I was able to get given the current limitations. Unfortunately we do not currently have control as to where the input elements (in this case, a slider) can be placed). I also had to switch from vega-lite to vega to implement this, so you'll want to make sure that the spec is set to vega in Deneb:
Ideally with your real dataset, you'd have fewer variables (attributes) and therefore, fewer charts in your SPLOM.If you need to change the initial size of your cells (which you probably should), you'll want to update this value:
Hey again Anonymous. Happy to help. Do you have a dummy dataset in mind? If not, I can generate one, you'll just need to make some updates to use the spec with your data.
- Anonymous3 years agoNot applicable
No I dont. Yes if you could generate one this will be great 😊
- giammariam3 years agoSolution Sage
Hey Anonymous. Here's my implementation of the SPLOM (scatterplot matrix). Your dataset will need to be flattened and the structure will consist of the following 4 fields:
- Index - a sequential integer identifier for the row
- Observation - The idenitifying name for each dot in the matrix
- Attribute - The variable that will show up on the x and y axes
- Value - The value for the attribute for the given observation
{ "$schema": "https://vega.github.io/schema/vega-lite/v5.json", "params": [{"name": "observation", "expr": "toString(brush['Observation'])"}], "data": { "name": "dataset", "url": "https://raw.githubusercontent.com/Giammaria/PublicFiles/master/pbi/pbi_community_help/20230309_trellis_scatter/data/mtcars_unpivoted.tsv", "format": {"parse": {"Index": "number", "Value": "number"}} }, "transform": [ {"joinaggregate": [{"op": "count", "as": "total_observation_count"}]}, { "calculate": "sequence(1,datum['total_observation_count']+1,1)", "as": "index_2" }, { "calculate": "split(replace(replace(join(datum['index_2'], ','), toString(datum['Index']), ''), ',,', ','), ',')", "as": "index_2" }, {"flatten": ["index_2"], "as": ["index_2"]}, {"filter": "datum['index_2']"}, {"calculate": "+datum['index_2']", "as": "index_2"}, { "lookup": "index_2", "from": { "data": {"name": "dataset"}, "key": "index", "fields": ["Attribute", "Value"] }, "as": ["attribute_2", "value_2"] }, { "calculate": "data('dataset')[datum['index_2']-1]", "as": "row_to_compare" }, {"filter": "datum['Observation']===datum['row_to_compare']['Observation']"}, {"calculate": "datum['row_to_compare']['Attribute']", "as": "attribute_2"}, {"calculate": "datum['row_to_compare']['Value']", "as": "value_2"}, { "calculate": "[datum['Attribute'], datum['attribute_2']]", "as": "variables" }, { "window": [{"op": "distinct", "field": "variables", "as": "facet_count"}], "frame": [null, null], "sort": [{"field": "facet_index", "order": "ascending"}] }, { "window": [ {"op": "dense_rank", "field": "variables", "as": "facet_index"} ], "sort": [{"field": "variables", "order": "ascending"}], "frame": [null, null] }, {"calculate": "floor(sqrt(datum['facet_count']))", "as": "row_count"}, { "calculate": "ceil(datum['facet_count']/datum['row_count'])", "as": "column_count" }, { "calculate": "datum['facet_index']%datum['column_count'] === 0 ? datum['column_count'] : datum['facet_index']%datum['column_count']", "as": "column" }, { "window": [{"op": "dense_rank", "as": "row"}], "groupby": ["column"], "frame": [null, 1], "sort": [{"field": "facet_index", "order": "ascending"}] }, { "window": [{"op": "row_number", "as": "facet_data_index"}], "groupby": ["facet_index"], "frame": [null, null] }, { "calculate": "datum['Attribute']+': '+toString(datum['Value'])", "as": "tooltipX" }, { "calculate": "datum['attribute_2']+': '+toString(datum['value_2'])", "as": "tooltipY" } ], "facet": { "row": {"field": "row", "title": null, "header": null, "type": "ordinal"}, "column": { "field": "column", "type": "ordinal", "title": null, "header": null } }, "spec": { "width": 150, "height": 150, "layer": [ { "name": "splom", "params": [ { "name": "brush", "select": { "type": "point", "on": "mouseover", "encodings": ["color"], "nearest": true, "clear": { "type": "mouseout" } } } ], "mark": {"type": "point", "filled": true}, "encoding": { "x": { "field": "Value", "type": "quantitative", "axis": {"title": null} }, "y": {"field": "value_2", "type": "quantitative", "title": null}, "color": { "condition": { "test": "observation===datum['Observation']", "field": "Observation", "type": "nominal", "legend": null }, "value": "steelblue" }, "size": { "condition": { "test": "observation===datum['Observation']", "value": 400 }, "value": 40 }, "tooltip": [ {"title": "Observation", "field": "Observation"}, {"title": "x", "field": "tooltipX"}, {"title": "y", "field": "tooltipY"} ] } }, { "name": "x-title", "transform": [{"filter": "datum['facet_data_index']===1"}], "mark": { "type": "text", "y": {"expr": "child_height"}, "yOffset": 25, "fontSize": 14 }, "encoding": {"text": {"field": "Attribute"}} }, { "name": "y-title", "transform": [{"filter": "datum['facet_data_index']===1"}], "mark": { "type": "text", "align": "center", "angle": 270, "x": {"expr": "0"}, "xOffset": -30, "fontSize": 14 }, "encoding": {"text": {"field": "attribute_2"}} } ] }, "resolve": { "axis": {"x": "independent", "y": "independent"}, "scale": {"x": "independent", "y": "independent"} }, "config": {"range": {"category": ["orange"]}} }​- Anonymous3 years agoNot applicable
Thanks a lot,
I sent you a lynkdin request...
Jim