Cannot convert undefined or null object - json

Been sat down trying to work this out for ages:/ telling me that it cannot convert undefined or null object. Any help would be very much appreciated:( Am trying to show the volume of trade of these major indexes. Am using the vega documentation and using different templates but nothing seems to be working for the visualisation i want to show
{"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": {
"text": "Trading volume of 5 major stock indexes from 2018-2022",
"subtitle":"Source: Yahoo Finance.",
"subtitleFontStyle":"italic",
"subtitleFontSize":10,
"anchor": "start",
"color": "black"
},
"description": "volume of stocks",
"data": {
"url": "https://raw.githubusercontent.com/andrewsnowdon/andrewsnowdon.github.io/main/graph1megasheet.csv",
"format": {"type": "csv"}
},
"height": 300,
"width": 300,
"mark": {"type": "area", "point": "false"},
"selection": {
"Stockname": {"type": "single", "fields": ["Stockname"], "bind": {"input": "select",
"options": [
"DAX",
"DOWJONES",
"FTSE100",
"NASDAQ",
"S&P500"
],
"name": "Select Index: "}
},
"encoding": {
"x": {
"field": "Date",
"type": "temporal",
"title": null,
"axis":{"grid":false}
},
"y": {
"field": "Volume",
"type": "quantitative",
"title": null,
"axis":{"grid":false}
},
"color": {
"field": "Stockname",
"type": "nominal",
"scale": {"scheme": "inferno"},
"title": null,
"legend": {
"orient": "bottom",
"columns":2,
"fillColor": "#FcFdFd"}
},
"opacity": {"condition": {"selection": "region", "value": 1}, "value": 0.1}
}
}}

Cannot convert undefined or null object errors will not be in your JSON schema that you shared. It would likely be a problem with the code referring to this schema. Either you are not actually getting the schema, or there is possibly a typo in the call.

You must have class with same properties as the JSON that you have.
For instance, if one property in you class has all characters with lowercase and JSON has the first char uppercase then it will be null.

Related

How to filter data using a slider in vega-lite?

I am using the following code to plot a bubble plot using vega-lite. I want to transform values as I change the year value using the slider. But it's not working.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Drag the sliders to highlight points.",
"data": {
"url": "https://raw.githubusercontent.com/shre2398/InformationVisualization/main/gapminder.tsv",
"format": {
"type": "tsv"
}
},
"title": {
"text": "Gapminder Global Indicators",
"anchor": "middle",
"fontSize": 16,
"fontWeight": 700
},
"config": {
"axis": {
"titleFontSize": 13,
"titleFontWeight": "bold"
}
},
"params": [{
"name": "CurrentYear",
"value": [{"year": 1977}],
"select": {"type": "point", "fields": ["year"]},
"bind": {
"year": {"input": "range", "min": 1952, "max": 2007, "step": 5}
}
},{
"name": "View",
"select": "interval",
"bind": "scales"
}],
"width": 650,
"height": 400,
"mark": {
"type": "circle",
"opacity": 0.8,
"stroke": "white",
"strokeWidth": 1
},
"encoding": {
"x": {
"field": "gdpPercap",
"type": "quantitative",
"axis": {"grid": false},
"scale": {
"type": "log",
"base": 10
}
},
"y": {
"field": "lifeExp",
"type": "quantitative",
"axis": {"title": ""}
},
"size": {
"field": "pop"
},
"color": {
"field": "continent"
}
}
}
If I add the following tranform block, it doesn't work.
"transform":[{"filter": {"param": "CurrentYear"}}]
I have already tried the following link :
https://vega.github.io/vega-lite/examples/interactive_query_widgets.html
It is because you are reading in your year column as strings, and then using a numerical selection to filter. You can see that the year values are strings in the "Data Viewer" tab. Reading in the data like this works with the transform filter you suggested above:
"data": {
"url": "https://raw.githubusercontent.com/shre2398/InformationVisualization/main/gapminder.tsv",
"format": {
"type": "tsv",
"parse": {"year": "number"}
}
}

Slider for chloropeth map Vega-lite

I am trying to add a slider for my chloropeth map of Europe in vega-lite, to filter the data by year. I currently have a map which just shows data from 2019 (colour coded), and I am trying to make a slider so I can change years and see how the colours have changed over time.
Here is my code so far:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": 300,
"height": 300,
"data": {
"url": "https://raw.githubusercontent.com/leakyMirror/map-of-europe/master/TopoJSON/europe.topojson",
"format": {"type": "topojson", "feature": "europe"}
},
"transform": [
{
"lookup": "properties.NAME",
"from": {
"data": {
"url": "https://raw.githubusercontent.com//jamesjeffery77/jamesjeffery77.github.io/main/share-electricity-low-carbon_fullDataset.csv"
},
"key": "country",
"fields": ["percentage"]
}
}
],
"params": [
{
"name": "year",
"value": 2019,
"bind": {
"input": "range",
"min": 1985,
"max": 2019,
"step": 1,
"name": "Select the year:"
}
}
],
"projection": {"type": "naturalEarth1"},
"mark": "geoshape",
"encoding": {
"color": {
"field": "percentage",
"type": "quantitative"},
"tooltip": [
{"field": "properties.NAME", "type": "nominal", "title": "country"},
{"field": "percentage", "type": "quantitative"}
]
}
}
I have been able to do make a bar chart using the same data which updates as I move the slider.The {"filter": "datum.year==year"} is what makes my bar chart able to do this, however it does not work on my chloropeth map (I have tried to add this within the "transform" array in both, with success for my bar chart). Here is the code for my bar chart in case that helps.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "",
"title": {
"text": "Thisisatest",
"subtitle":
"hellohello Source: OurWorldInData",
"subtitleFontStyle": "italic",
"subtitleFontSize": 10,
"anchor": "start",
"color": "black"
},
"data": {
"url": "https://raw.githubusercontent.com//jamesjeffery77/jamesjeffery77.github.io/main/share-electricity-low-carbon_fullDataset.csv"
},
"height": 300,
"width": 350,
"mark": {"type": "bar", "color": "skyblue"},
"transform": [
{"filter": "datum.year==year"},
{"filter": {
"field": "country",
"oneOf": [
"United Kingdom", "Spain", "France", "Netherlands", "Portugal", "Italy", "Poland", "Albania", "Germany", "Belgium", "Austria", "Denmark"]}
}
],
"params": [
{
"name": "year",
"value": 2019,
"bind": {
"input": "range",
"min": 1985,
"max": 2019,
"step": 1,
"name": "Select the year:"
}
}
],
"encoding": {
"y": {
"field": "percentage",
"type": "quantitative",
"title": "Percentage of low carbon energy",
"axis": {"grid": false}
},
"x": {
"field": "country",
"type": "nominal",
"title": "",
"axis": {"grid": false, "labelAngle": 20},
"sort": "-y"
},
"tooltip": [
{"field": "country", "title": "Country"},
{"field": "percentage", "title": "percentage of low carbon energy"}
]
}
}
What am I am doing wrong? Would appreciate any help! :)
Thanks
It was almost correct but in your lookup transform you need to provide the fields which you are going to be required in your final data like year field. Since there was no year field the filter transform was not working.
Below is the modified config or refer editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": 300,
"height": 300,
"data": {
"url": "https://raw.githubusercontent.com//jamesjeffery77/jamesjeffery77.github.io/main/share-electricity-low-carbon_fullDataset.csv"
},
"transform": [
{
"lookup": "country",
"from": {
"data": {
"url": "https://raw.githubusercontent.com/leakyMirror/map-of-europe/master/TopoJSON/europe.topojson",
"format": {"type": "topojson", "feature": "europe"}
},
"key": "properties.NAME",
"fields": ["properties", "type", "geometry"]
}
},
{"filter": "datum.year==year"}
],
"params": [
{
"name": "year",
"value": 2019,
"bind": {
"input": "range",
"min": 1985,
"max": 2030,
"step": 1,
"name": "Select the year:"
}
}
],
"projection": {"type": "naturalEarth1"},
"mark": "geoshape",
"encoding": {
"color": {"field": "percentage", "type": "quantitative"},
"tooltip": [
{"field": "properties.NAME", "type": "nominal", "title": "country"},
{"field": "percentage", "type": "quantitative"}
]
}
}
Edit
I have inverted the main data and lookup data, which seems to bring all the years for your countries. Let me know if this works.

Set domainMin to 6 months before max date in data

I have the following Vega-Lite chart:
Open the Chart in the Vega Editor
Currently, I have the scale set as follows:
"scale": {"domainMin": "2021-06-01"}
However, what I really want is for the domainMin to be automatically calculated to be 6 months before the latest date in the notification_date field in the data.
I've looked at aggregate and expressions, but it's not exactly clear.
How can I get the maximum value of notification_date and subtract 6 months from it, and use that in "domainMin"?
Edit: To clarify, I don't want to filter the data. I want the user to be able to zoom out or pan to see the data outside the initial 6-month window. I get exactly what I want with "scale": {"domainMin": "2021-06-01"}, but this becomes out-of-date very quickly.
I have tried giving params and expr to domainMin, but I was unable to use the data fields in expr through datum.
The 2nd approach I tried will work for you, in this you will need to make use of joinaggregate/calculate/filter transforms. You will manually gather the max year and max months and then use it to filter your data.
Below is the modified config or refer the editor url:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"width": "container",
"height": "container",
"config": {
"group": {"fill": "#e5e5e5"},
"arc": {"fill": "#2b2c39"},
"area": {"fill": "#2b2c39"},
"line": {"stroke": "#2b2c39"},
"path": {"stroke": "#2b2c39"},
"rect": {"fill": "#2b2c39"},
"shape": {"stroke": "#2b2c39"},
"symbol": {"fill": "#2b2c39"},
"range": {
"category": [
"#2283a2",
"#003e6a",
"#a1ce5e",
"#FDBE13",
"#F2727E",
"#EA3F3F",
"#25A9E0",
"#F97A08",
"#41BFB8",
"#518DCA",
"#9460A8",
"#6F7D84",
"#D1DCA5"
]
}
},
"title": "South Western Sydney Cumulative and Daily COVID-19 Cases by LGA",
"data": {
"url": "https://davidwales.github.io/nsw-covid-19-data/confirmed_cases_table1_location.csv"
},
"transform": [
{
"filter": {
"and": [
{"field": "lhd_2010_name", "equal": "South Western Sydney"},
{"not": {"field": "lga_name19", "equal": "Penrith"}}
]
}
},
{"calculate": "utcyear(datum.notification_date)", "as": "yearNumber"},
{"calculate": "utcmonth(datum.notification_date)", "as": "monthNumber"},
{
"window": [
{"op": "count", "field": "notification_date", "as": "cumulative_count"}
],
"frame": [null, 0]
},
{
"joinaggregate": [
{"field": "monthNumber", "op": "max", "as": "max_month_count"},
{"field": "yearNumber", "op": "max", "as": "max_year"}
]
},
{"calculate": "abs(datum.max_month_count-6)", "as": "min_month_count"},
{
"filter": "datum.min_month_count < datum.monthNumber && datum.max_year === datum.yearNumber"
}
],
"layer": [
{
"selection": {
"date": {"type": "interval", "bind": "scales", "encodings": ["x"]}
},
"mark": {"type": "bar", "tooltip": true},
"encoding": {
"x": {
"timeUnit": "yearmonthdate",
"field": "notification_date",
"type": "temporal",
"title": "Date"
},
"color": {
"field": "lga_name19",
"type": "nominal",
"title": "LGA",
"legend": {"orient": "top", "columns": 4}
},
"y": {
"aggregate": "count",
"field": "lga_name19",
"type": "quantitative",
"title": "Cases",
"axis": {"title": "Daily Cases by SWS LGA"}
}
}
},
{
"mark": "line",
"encoding": {
"x": {
"timeUnit": "yearmonthdate",
"field": "notification_date",
"title": "Date",
"type": "temporal"
},
"y": {
"aggregate": "max",
"field": "cumulative_count",
"type": "quantitative",
"axis": {"title": "Cumulative Cases"}
}
}
}
],
"resolve": {"scale": {"y": "independent"}}
}
A bit simpler approach to filter approximately the last six months of data might look like this:
"transform": [
...,
{"joinaggregate": [{"op": "max", "field": "notification_date", "as": "last_date"}]},
{"filter": "datum.notification_date > datum.last_date - 6 * 30 * 24 * 60 * 60 * 1000"}
]
It makes use of the fact that dates are stored as millisecond time-stamps, and has the benefit that it will work across year boundaries.
This is not quite an answer to the question you asked, but if your data is reasonably up-to-date (that is, the most recent data point is close to the current date), you can do something like this:
"scale": { "domainMin": { "expr": "timeOffset('month', now(), -6)" } }

Am confused as to why my graph isn't showing up in vega?

My graph isn't plotting in vega despite no error that i can see? Confused as to why this seems to be the case. I don't quite understand what I would've done wrong for the graph to not appear on the page. This is a template that I downloaded
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": {
"text": "My new Covid Chart",
"subtitle":"This is my new chart",
"subtitleFontStyle":"italic",
"subtitleFontSize":10,
"anchor": "start",
"color": "black"
},
"data": {
"url": "https://api.coronavirus.data.gov.uk/v2/data?areaType=overview&metric=newCasesBySpecimenDate&format=csv",
"format": {"type": "csv"}
},
"transform":[
{"filter": {
"field": "areaName",
"oneOf": ["Bristol, City of", "Bolton", "Glasgow City"]}
}
],
"height": 300,
"width": 310,
"mark": {"type": "line", "point": false},
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"title": null,
"axis": {"grid": false}
},
"y": {
"field": "newCasesByPublishDateRollingRate",
"type": "quantitative",
"title": null,
"axis": {"grid": false}
},
"color": {
"field": "areaName",
"type": "nominal",
"scale": {"scheme": "set1"},
"title": "LEGEND TITLE",
"legend": {
"orient": "top-left",
"fillColor": "#FcFdFd"}
}
}
}
You had applied filter transform which was not satisfying the criteria and making the data empty. Also the newCasesByPublishDateRollingRate field for y-axis used was not present in your data, instead I tried the field newCasesBySpecimenDate which worked.
Adding the correct config below or refer the editor:
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": {
"text": "My new Covid Chart",
"subtitle": "This is my new chart",
"subtitleFontStyle": "italic",
"subtitleFontSize": 10,
"anchor": "start",
"color": "black"
},
"data": {
"url": "https://api.coronavirus.data.gov.uk/v2/data?areaType=overview&metric=newCasesBySpecimenDate&format=csv",
"format": {"type": "csv"}
},
"height": 300,
"width": 310,
"mark": {"type": "line", "point": false},
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"title": null,
"axis": {"grid": false}
},
"y": {
"field": "newCasesBySpecimenDate",
"type": "quantitative",
"title": null,
"axis": {"grid": false}
},
"color": {
"field": "areaName",
"type": "nominal",
"scale": {"scheme": "set1"},
"title": "LEGEND TITLE",
"legend": {"orient": "top-left", "fillColor": "#FcFdFd"}
}
}
}

Vega-Lite map not showing up with no error

I modified this example Vega-Lite map plot https://vega.github.io/vega-lite/examples/geo_trellis.html but nothing shows up, and there are no errors.
Here is the code
"transform": [
{
"lookup": "id",
"from": {
"data": {
"url": "data/us-10m.json",
"format": {"type": "topojson", "feature": "states"}
},
"key": "id"
},
"as": "geo"
}
],
"projection": {"type": "albersUsa"},
"mark": "geoshape",
"encoding": {
"shape": {"field": "geo", "type": "geojson"},
"color": {"field": "count", "type": "quantitative"}
}
Open the Chart in the Vega Editor
I'm not sure what could possibly be wrong. Thanks for the help!
Your data contains rows that are missing the "id" entry, which leads to null geo entries in the joined data. If you filter out these invalid values, it works as expected for the defined rows (vega editor):
"transform": [
{"filter": "isValid(datum.id)"},
{
"lookup": "id",
"from": {
"data": {
"url": "data/us-10m.json",
"format": {"type": "topojson", "feature": "states"}
},
"key": "id"
},
"as": "geo"
}
],