Extension:Graph/Demo

From Linux Web Expert

This page shows some examples of what Graph extension can produce. Graphs use Vega grammar (documentation) as underlying technology. Vega team is working on other tools to make Graphs easier to use. For interactive graphs this tutorial will explain building graphs step by step. For other graph ideas, see Vega examples.

Graph templates

The easiest way to use graphs is via pre-built templates such as the Template:Graph:Chart (available on many Wikipedias), or more specialized PieChart. Graph:Chart supports many common graph types such as line, area, and pie charts:

{{Graph:Chart|width=600|height=100|xAxisTitle=X|yAxisTitle=Y
 |type=rect|x=1,2,3,4,5,6,7,8|y=10,12,6,14,2,10,7,9}}

{{Graph:Chart|width=100|height=100|type=pie|legend=Legende
 |x=A,B,C,D,E,F,G,H,I|y1=100,200,150,300,100,100,150,50,200
 |y2=7,8,9,8,8,9,10,9,5|showValues=}}

{{Graph:Chart|width=400|height=100|xAxisTitle=X|yAxisTitle=Y
 |legend=Legend|type=stackedarea|x=1,2,3,4,5,6|y1=10,12,6,14,2,10
 |y2=2,4,6,8,13,11|interpolate=monotone|colors=seagreen,orchid}}

<graph fallback="" fallbackWidth="">{"legends":[],"scales":[{"type":"band","name":"x","domain":{"data":"chart","field":"x"},"padding":0.2,"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y"},"zero":true,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":{"scheme":"category10"}}],"marks":[{"encode":{"hover":{"fill":{"value":"red"}},"update":{"fill":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y"},"x":{"scale":"x","field":"x"},"y2":{"scale":"y","value":0},"width":{"scale":"x","offset":-1,"band":true},"fill":{"scale":"color","field":"series"}}},"type":"rect","from":{"data":"chart"}}],"data":[{"transform":[],"format":{"parse":{"y":"number","x":"number"},"type":"json"},"name":"chart","values":[{"y":10,"series":"y","index":1,"x":1},{"y":12,"series":"y","index":1,"x":2},{"y":6,"series":"y","index":1,"x":3},{"y":14,"series":"y","index":1,"x":4},{"y":2,"series":"y","index":1,"x":5},{"y":10,"series":"y","index":1,"x":6},{"y":7,"series":"y","index":1,"x":7},{"y":9,"series":"y","index":1,"x":8}]}],"height":100,"axes":[{"orient":"bottom","title":"X","encode":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"scale":"x","format":"d","tickMinStep":1,"grid":false},{"orient":"left","encode":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"title":"Y","tickCount":8,"scale":"y","format":"d","tickMinStep":1,"grid":false}],"$schema":"https://vega.github.io/schema/vega/v5.json","width":400} </graph> <graph fallback="" fallbackWidth="">{"legends":[{"orient":"top-right","title":"Legende","labelColor":"#54595d","stroke":"color","titleColor":"#54595d","fill":"color"}],"scales":[{"domain":{"data":"chart","field":"x"},"type":"ordinal","name":"color","range":{"scheme":"category10"}},{"range":[0,50],"type":"linear","name":"r","domain":{"data":"chart","field":"r"}}],"marks":[{"encode":{"enter":{"y":{"value":50},"x":{"value":50},"fill":{"scale":"color","field":"x"}},"update":{"endAngle":{"field":"endAngle"},"innerRadius":{"value":0},"outerRadius":{"scale":"r","value":50,"field":"r"},"startAngle":{"field":"startAngle"},"stroke":{"value":"white"},"fill":{"scale":"color","field":"x"},"strokeWidth":{"value":1}},"hover":{"fill":{"value":"red"}}},"type":"arc","from":{"data":"chart"}},{"encode":{"enter":{"theta":{"signal":"(datum.startAngle + datum.endAngle)/2"},"baseline":{"value":"middle"},"align":{"value":"center"},"text":{"field":"y"},"y":{"value":50},"x":{"value":50},"fontSize":{"value":5},"angle":{"mult":57.29577951308232,"field":"layout_mid"},"radius":{"scale":"r","offset":-15,"field":"r"},"fill":{"value":"white"}}},"type":"text","from":{"data":"chart"}}],"data":[{"transform":[{"type":"pie","field":"y"}],"format":{"parse":{"y":"number","x":"string","r":"number"},"type":"json"},"name":"chart","values":[{"y":100,"x":"A","r":7},{"y":200,"x":"B","r":8},{"y":150,"x":"C","r":9},{"y":300,"x":"D","r":8},{"y":100,"x":"E","r":8},{"y":100,"x":"F","r":9},{"y":150,"x":"G","r":10},{"y":50,"x":"H","r":9},{"y":200,"x":"I","r":5}]}],"height":100,"axes":[],"$schema":"https://vega.github.io/schema/vega/v5.json","width":200} </graph> <graph fallback="" fallbackWidth="">{"legends":[{"title":"Legend","labelColor":"#54595d","stroke":"color","titleColor":"#54595d","fill":"color"}],"scales":[{"type":"linear","name":"x","domain":{"data":"chart","field":"x"},"zero":false,"range":"width","nice":true},{"type":"linear","name":"y","domain":{"data":"chart","field":"y1"},"zero":true,"range":"height","nice":true},{"domain":{"data":"chart","field":"series"},"type":"ordinal","name":"color","range":["seagreen","orchid"]}],"marks":[{"type":"group","marks":[{"encode":{"hover":{"fill":{"value":"red"}},"update":{"fill":{"scale":"color","field":"series"}},"enter":{"y":{"scale":"y","field":"y1"},"interpolate":{"value":"monotone"},"y2":{"scale":"y","field":"y0"},"x":{"scale":"x","field":"x"},"fill":{"scale":"color","field":"series"}}},"type":"area","from":{"data":"facet"}}],"from":{"facet":{"name":"facet","data":"chart","groupby":"series"}}}],"data":[{"transform":[{"field":"y","type":"stack","sort":{"field":"index"},"groupby":["x"]}],"format":{"parse":{"y":"number","x":"number"},"type":"json"},"name":"chart","values":[{"y":10,"series":"y1","index":1,"x":1},{"y":12,"series":"y1","index":1,"x":2},{"y":6,"series":"y1","index":1,"x":3},{"y":14,"series":"y1","index":1,"x":4},{"y":2,"series":"y1","index":1,"x":5},{"y":10,"series":"y1","index":1,"x":6},{"y":2,"series":"y2","index":2,"x":1},{"y":4,"series":"y2","index":2,"x":2},{"y":6,"series":"y2","index":2,"x":3},{"y":8,"series":"y2","index":2,"x":4},{"y":13,"series":"y2","index":2,"x":5},{"y":11,"series":"y2","index":2,"x":6}]}],"height":100,"axes":[{"orient":"bottom","title":"X","encode":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"scale":"x","format":"d","tickMinStep":1,"grid":false},{"orient":"left","encode":{"title":{"fill":{"value":"#54595d"}},"grid":{"stroke":{"value":"#54595d"}},"ticks":{"stroke":{"value":"#54595d"}},"axis":{"strokeWidth":{"value":2},"stroke":{"value":"#54595d"}},"labels":{"fill":{"value":"#54595d"}}},"title":"Y","tickCount":8,"scale":"y","format":"d","tickMinStep":1,"grid":false}],"$schema":"https://vega.github.io/schema/vega/v5.json","width":400} </graph>

Vega 2.0 interactive examples

Extension:Graph/Demo/Dimpvis From https://vega.github.io/editor/#/examples/vega/global-development <graph mode=interactive title="Life Expectancy vs Family Size (click and drag)"> {

 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "description": "An interactive scatter plot of global health statistics by country and year.",
 "width": 800,
 "height": 600,
 "padding": 5,
 "data": [
   {
     "name": "gapminder",
     "url": "https://www.mediawiki.org/wiki/Extension:Graph/data/gapminder-json?action=raw"
   },
   {
     "name": "clusters",
     "values": [
       {"id": 0, "name": "South Asia"},
       {"id": 1, "name": "Europe & Central Asia"},
       {"id": 2, "name": "Sub-Saharan Africa"},
       {"id": 3, "name": "America"},
       {"id": 4, "name": "East Asia & Pacific"},
       {"id": 5, "name": "Middle East & North Africa"}
     ]
   },
   {
     "name": "country_timeline",
     "source": "gapminder",
     "transform": [
       {"type": "filter", "expr": "timeline && datum.country == timeline.country"},
       {"type": "collect", "sort": {"field": "year"}}
     ]
   },
   {
     "name": "thisYear",
     "source": "gapminder",
     "transform": [
       {"type": "filter", "expr": "datum.year == currentYear"}
     ]
   },
   {
     "name": "prevYear",
     "source": "gapminder",
     "transform": [
       {"type": "filter", "expr": "datum.year == currentYear - stepYear"}
     ]
   },
   {
     "name": "nextYear",
     "source": "gapminder",
     "transform": [
       {"type": "filter", "expr": "datum.year == currentYear + stepYear"}
     ]
   },
   {
     "name": "countries",
     "source": "gapminder",
     "transform": [
       {"type": "aggregate", "groupby": ["country"]}
     ]
   },
   {
     "name": "interpolate",
     "source": "countries",
     "transform": [
       {
         "type": "lookup",
         "from": "thisYear", "key": "country",
         "fields": ["country"], "as": ["this"],
         "default": {}
       },
       {
         "type": "lookup",
         "from": "prevYear", "key": "country",
         "fields": ["country"], "as": ["prev"],
         "default": {}
       },
       {
         "type": "lookup",
         "from": "nextYear", "key": "country",
         "fields": ["country"], "as": ["next"],
         "default": {}
       },
       {
         "type": "formula",
         "as": "target_fertility",
         "expr": "interYear > currentYear ? datum.next.fertility : (datum.prev.fertility||datum.this.fertility)"
       },
       {
         "type": "formula",
         "as": "target_life_expect",
         "expr": "interYear > currentYear ? datum.next.life_expect : (datum.prev.life_expect||datum.this.life_expect)"
       },
       {
         "type": "formula",
         "as": "inter_fertility",
         "expr": "interYear==2000 ? datum.this.fertility : datum.this.fertility + (datum.target_fertility-datum.this.fertility) * abs(interYear-datum.this.year)/5"
       },
       {
         "type": "formula",
         "as": "inter_life_expect",
         "expr": "interYear==2000 ? datum.this.life_expect : datum.this.life_expect + (datum.target_life_expect-datum.this.life_expect) * abs(interYear-datum.this.year)/5"
       }
     ]
   },
   {
     "name": "trackCountries",
     "on": [
       {"trigger": "active", "toggle": "{country: active.country}"}
     ]
   }
 ],
 "signals": [
   { "name": "minYear", "value": 1955 },
   { "name": "maxYear", "value": 2005 },
   { "name": "stepYear", "value": 5 },
   {
     "name": "active",
     "value": {},
     "on": [
       {"events": "@point:mousedown, @point:touchstart", "update": "datum"},
       {"events": "window:mouseup, window:touchend", "update": "{}"}
     ]
   },
   { "name": "isActive", "update": "active.country" },
   {
     "name": "timeline",
     "value": {},
     "on": [
       {"events": "@point:mouseover", "update": "isActive ? active : datum"},
       {"events": "@point:mouseout", "update": "active"},
       {"events": {"signal": "active"}, "update": "active"}
     ]
   },
   {
     "name": "tX",
     "on": [{
       "events": "mousemove!, touchmove!",
       "update": "isActive ? scale('x', active.this.fertility) : tX"
     }]
   },
   {
     "name": "tY",
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? scale('y', active.this.life_expect) : tY"
     }]
   },
   {
     "name": "pX",
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? scale('x', active.prev.fertility) : pX"
     }]
   },
   {
     "name": "pY",
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? scale('y', active.prev.life_expect) : pY"
     }]
   },
   {
     "name": "nX",
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? scale('x', active.next.fertility) : nX"
     }]
   },
   {
     "name": "nY",
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? scale('y', active.next.life_expect) : nY"
     }]
   },
   {
     "name": "thisDist",
     "value": 0,
     "on":[{
       "events": "mousemove, touchmove",
       "update": "isActive ? sqrt(pow(x()-tX, 2) + pow(y()-tY, 2)) : thisDist"
     }]
   },
   {
     "name": "prevDist",
     "value": 0,
     "on":[{
       "events": "mousemove, touchmove",
       "update": "isActive ? sqrt(pow(x()-pX, 2) + pow(y()-pY, 2)): prevDist"
     }]
   },
   {
     "name": "nextDist",
     "value": 0,
     "on":[{
       "events": "mousemove, touchmove",
       "update": "isActive ? sqrt(pow(x()-nX, 2) + pow(y()-nY, 2)) : nextDist"
     }]
   },
   {
     "name": "prevScore",
     "value": 0,
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? ((pX-tX) * (x()-tX) + (pY-tY) * (y()-tY))/prevDist || -999999 : prevScore"
     }]
   },
   {
     "name": "nextScore",
     "value": 0,
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? ((nX-tX) * (x()-tX) + (nY-tY) * (y()-tY))/nextDist || -999999 : nextScore"
     }]
   },
   {
     "name": "interYear",
     "value": 1980,
     "on": [{
       "events": "mousemove, touchmove",
       "update": "isActive ? (min(maxYear, currentYear+5, max(minYear, currentYear-5, prevScore > nextScore ? (currentYear - 2.5*prevScore/sqrt(pow(pX-tX, 2) + pow(pY-tY, 2))) : (currentYear + 2.5*nextScore/sqrt(pow(nX-tX, 2) + pow(nY-tY, 2)))))) : interYear"
     }]
   },
   {
     "name": "currentYear",
     "value": 1980,
     "on":[{
       "events": "mousemove, touchmove",
       "update": "isActive ? (min(maxYear, max(minYear, prevScore > nextScore ? (thisDist < prevDist ? currentYear : currentYear-5) : (thisDist < nextDist ? currentYear : currentYear+5)))) : currentYear"
     }]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "linear", "nice": true,
     "domain": {"data": "gapminder", "field": "fertility"},
     "range": "width"
   },
   {
     "name": "y",
     "type": "linear", "nice": true, "zero": false,
     "domain": {"data": "gapminder", "field": "life_expect"},
     "range": "height"
   },
   {
     "name": "color",
     "type": "ordinal",
     "domain": {"data": "gapminder", "field": "cluster"},
     "range": "category"
   },
   {
     "name": "label",
     "type": "ordinal",
     "domain": {"data": "clusters", "field": "id"},
     "range": {"data": "clusters", "field": "name"}
   }
 ],
 "axes": [
   {
     "title": "Fertility",
     "orient": "bottom", "scale": "x",
     "grid": true, "tickCount": 5
   },
   {
     "title": "Life Expectancy",
     "orient": "left", "scale": "y",
     "grid": true, "tickCount": 5
   }
 ],
 "legends": [
   {
     "fill": "color",
     "title": "Region",
     "orient": "right",
     "encode": {
       "symbols": {
         "enter": {
           "fillOpacity": {"value": 0.5}
         }
       },
       "labels": {
         "update": {
           "text": {"scale": "label", "field": "value"}
         }
       }
     }
   }
 ],
 "marks": [
   {
     "type": "text",
     "encode": {
       "update": {
         "text": {"signal": "currentYear"},
         "x": {"value": 300},
         "y": {"value": 300},
         "fill": {"value": "grey"},
         "fillOpacity": {"value": 0.25},
         "fontSize": {"value": 100}
       }
     }
   },
   {
     "type": "text",
     "from": {"data": "country_timeline"},
     "interactive": false,
     "encode": {
       "enter": {
         "x": {"scale": "x", "field": "fertility", "offset": 5},
         "y": {"scale": "y", "field": "life_expect"},
         "fill": {"value": "#555"},
         "fillOpacity": {"value": 0.6},
         "text": {"field": "year"}
       }
     }
   },
   {
     "type": "line",
     "from": {"data": "country_timeline"},
     "encode": {
       "update": {
         "x": {"scale": "x", "field": "fertility"},
         "y": {"scale": "y", "field": "life_expect"},
         "stroke": {"value": "#bbb"},
         "strokeWidth": {"value": 5},
         "strokeOpacity": {"value": 0.5}
       }
     }
   },
   {
     "name": "point",
     "type": "symbol",
     "from": {"data": "interpolate"},
     "encode": {
       "enter": {
         "fill": {"scale": "color", "field": "this.cluster"},
         "size": {"value": 150}
       },
       "update": {
         "x": {"scale": "x", "field": "inter_fertility"},
         "y": {"scale": "y", "field": "inter_life_expect"},
         "fillOpacity": [
           {
             "test": "datum.country==timeline.country || indata('trackCountries', 'country', datum.country)",
             "value": 1
           },
           {"value": 0.5}
         ]
       }
     }
   },
   {
     "type": "text",
     "from": {"data": "interpolate"},
     "interactive": false,
     "encode": {
       "enter": {
         "fill": {"value": "#333"},
         "fontSize": {"value": 14},
         "fontWeight": {"value": "bold"},
         "text": {"field": "country"},
         "align": {"value": "center"},
         "baseline": {"value": "bottom"}
       },
       "update": {
         "x": {"scale": "x", "field": "inter_fertility"},
         "y": {"scale": "y", "field": "inter_life_expect", "offset": -7},
         "fillOpacity": [
           {
             "test": "datum.country==timeline.country || indata('trackCountries', 'country', datum.country)",
             "value": 0.8
           },
           {"value": 0}
         ]
       }
     }
   }
 ]

} </graph>

Extension:Graph/Demo/Airports From https://vega.github.io/editor/#/examples/vega/airport-connections <graph mode=interactive title="Flight Routes in USA"> { "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "Interactive map of U.S. airport connections in 2008.", "width": 900, "height": 560, "padding": {"top": 25, "left": 0, "right": 0, "bottom": 0}, "autosize": "none",

"signals": [ { "name": "scale", "value": 1200, "bind": {"input": "range", "min": 500, "max": 3000} }, { "name": "translateX", "value": 450, "bind": {"input": "range", "min": -500, "max": 1200} }, { "name": "translateY", "value": 260, "bind": {"input": "range", "min": -300, "max": 700} }, { "name": "shape", "value": "line", "bind": {"input": "radio", "options": ["line", "curve"]} }, { "name": "hover", "value": null, "on": [ {"events": "@cell:mouseover", "update": "datum"}, {"events": "@cell:mouseout", "update": "null"} ] }, { "name": "title", "value": "U.S. Airports, 2008", "update": "hover ? hover.name + ' (' + hover.iata + ')' : 'U.S. Airports, 2008'" }, { "name": "cell_stroke", "value": null, "on": [ {"events": "dblclick", "update": "cell_stroke ? null : 'brown'"}, {"events": "mousedown!", "update": "cell_stroke"} ] } ],

"data": [ { "name": "states", "url": "https://www.mediawiki.org/wiki/Extension:Graph/Demo/Airports/us-10m.json?action=raw", "format": {"type": "topojson", "feature": "states"}, "transform": [ { "type": "geopath", "projection": "projection" } ] }, { "name": "traffic", "url": "https://www.mediawiki.org/wiki/Extension:Graph/Demo/Airports/flights-airport.csv?action=raw", "format": {"type": "csv", "parse": "auto"}, "transform": [ { "type": "aggregate", "groupby": ["origin"], "fields": ["count"], "ops": ["sum"], "as": ["flights"] } ] }, { "name": "airports", "url": "https://www.mediawiki.org/wiki/Extension:Graph/Demo/Airports/airports.csv?action=raw", "format": {"type": "csv","parse": "auto" }, "transform": [ { "type": "lookup", "from": "traffic", "key": "origin", "fields": ["iata"], "as": ["traffic"] }, { "type": "filter", "expr": "datum.traffic != null" }, { "type": "geopoint", "projection": "projection", "fields": ["longitude", "latitude"] }, { "type": "filter", "expr": "datum.x != null && datum.y != null" }, { "type": "voronoi", "x": "x", "y": "y" }, { "type": "collect", "sort": { "field": "traffic.flights", "order": "descending" } } ] }, { "name": "routes", "url": "https://www.mediawiki.org/wiki/Extension:Graph/Demo/Airports/flights-airport.csv?action=raw", "format": {"type": "csv", "parse": "auto"}, "transform": [ { "type": "filter", "expr": "hover && hover.iata == datum.origin" }, { "type": "lookup", "from": "airports", "key": "iata", "fields": ["origin", "destination"], "as": ["source", "target"] }, { "type": "filter", "expr": "datum.source && datum.target" }, { "type": "linkpath", "shape": {"signal": "shape"} } ] } ],

"projections": [ { "name": "projection", "type": "albersUsa", "scale": {"signal": "scale"}, "translate": [{"signal": "translateX"}, {"signal": "translateY"}] } ],

"scales": [ { "name": "size", "type": "linear", "domain": {"data": "traffic", "field": "flights"}, "range": [16, 1000] } ],

"marks": [ { "type": "path", "from": {"data": "states"}, "encode": { "enter": { "fill": {"value": "#dedede"}, "stroke": {"value": "white"} }, "update": { "path": {"field": "path"} } } }, { "type": "symbol", "from": {"data": "airports"}, "encode": { "enter": { "size": {"scale": "size", "field": "traffic.flights"}, "fill": {"value": "steelblue"}, "fillOpacity": {"value": 0.8}, "stroke": {"value": "white"}, "strokeWidth": {"value": 1.5} }, "update": { "x": {"field": "x"}, "y": {"field": "y"} } } }, { "type": "path", "name": "cell", "from": {"data": "airports"}, "encode": { "enter": { "fill": {"value": "transparent"}, "strokeWidth": {"value": 0.35} }, "update": { "path": {"field": "path"}, "stroke": {"signal": "cell_stroke"} } } }, { "type": "path", "interactive": false, "from": {"data": "routes"}, "encode": { "enter": { "path": {"field": "path"}, "stroke": {"value": "black"}, "strokeOpacity": {"value": 0.35} } } }, { "type": "text", "interactive": false, "encode": { "enter": { "x": {"value": 895}, "y": {"value": 0}, "fill": {"value": "black"}, "fontSize": {"value": 20}, "align": {"value": "right"} }, "update": { "text": {"signal": "title"} } } } ] } </graph>

Extension:Graph/Demo/OverviewDetail From https://vega.github.io/editor/#/examples/vega/overview-plus-detail <graph mode=interactive title="Zoomable Graph"> {

 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "description": "Area charts of stock prices, with an interactive overview and filtered detail views.",
 "width": 720,
 "height": 480,
 "padding": 5,
 "data": [
   {
     "name": "sp500",
     "url": "https://www.mediawiki.org/wiki/Extension:Graph/data/sp500-csv?action=raw",
     "format": {"type": "csv", "parse": {"price": "number", "date": "date"}}
   }
 ],
 "signals": [
   {
     "name": "detailDomain"
   }
 ],
 "marks": [
   {
     "type": "group",
     "name": "detail",
     "encode": {
       "enter": {
         "height": {"value": 390},
         "width": {"value": 720}
       }
     },
     "scales": [
       {
         "name": "xDetail",
         "type": "time",
         "range": "width",
         "domain": {"data": "sp500", "field": "date"},
         "domainRaw": {"signal": "detailDomain"}
       },
       {
         "name": "yDetail",
         "type": "linear",
         "range": [390, 0],
         "domain": {"data": "sp500", "field": "price"},
         "nice": true, "zero": true
       }
     ],
     "axes": [
       {"orient": "bottom", "scale": "xDetail"},
       {"orient": "left", "scale": "yDetail"}
     ],
     "marks": [
       {
         "type": "group",
         "encode": {
           "enter": {
             "height": {"field": {"group": "height"}},
             "width": {"field": {"group": "width"}},
             "clip": {"value": true}
           }
         },
         "marks": [
           {
             "type": "area",
             "from": {"data": "sp500"},
             "encode": {
               "update": {
                 "x": {"scale": "xDetail", "field": "date"},
                 "y": {"scale": "yDetail", "field": "price"},
                 "y2": {"scale": "yDetail", "value": 0},
                 "fill": {"value": "steelblue"}
               }
             }
           }
         ]
       }
     ]
   },
   {
     "type": "group",
     "name": "overview",
     "encode": {
       "enter": {
         "x": {"value": 0},
         "y": {"value": 430},
         "height": {"value": 70},
         "width": {"value": 720},
         "fill": {"value": "transparent"}
       }
     },
     "signals": [
       {
         "name": "brush", "value": 0,
         "on": [
           {
             "events": "@overview:mousedown",
             "update": "[x(), x()]"
           },
           {
             "events": "[@overview:mousedown, window:mouseup] > window:mousemove!",
             "update": "[brush[0], clamp(x(), 0, width)]"
           },
           {
             "events": {"signal": "delta"},
             "update": "clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
           }
         ]
       },
       {
         "name": "anchor", "value": null,
         "on": [{"events": "@brush:mousedown", "update": "slice(brush)"}]
       },
       {
         "name": "xdown", "value": 0,
         "on": [{"events": "@brush:mousedown", "update": "x()"}]
       },
       {
         "name": "delta", "value": 0,
         "on": [
           {
             "events": "[@brush:mousedown, window:mouseup] > window:mousemove!",
             "update": "x() - xdown"
           }
         ]
       },
       {
         "name": "detailDomain",
         "push": "outer",
         "on": [
           {
             "events": {"signal": "brush"},
             "update": "span(brush) ? invert('xOverview', brush) : null"
           }
         ]
       }
     ],
     "scales": [
       {
         "name": "xOverview",
         "type": "time",
         "range": "width",
         "domain": {"data": "sp500", "field": "date"}
       },
       {
         "name": "yOverview",
         "type": "linear",
         "range": [70, 0],
         "domain": {"data": "sp500", "field": "price"},
         "nice": true, "zero": true
       }
     ],
     "axes": [
       {"orient": "bottom", "scale": "xOverview"}
     ],
     "marks": [
       {
         "type": "area",
         "interactive": false,
         "from": {"data": "sp500"},
         "encode": {
           "update": {
             "x": {"scale": "xOverview", "field": "date"},
             "y": {"scale": "yOverview", "field": "price"},
             "y2": {"scale": "yOverview", "value": 0},
             "fill": {"value": "steelblue"}
           }
         }
       },
       {
         "type": "rect",
         "name": "brush",
         "encode": {
           "enter": {
             "y": {"value": 0},
             "height": {"value": 70},
             "fill": {"value": "#333"},
             "fillOpacity": {"value": 0.2}
           },
           "update": {
             "x": {"signal": "brush[0]"},
             "x2": {"signal": "brush[1]"}
           }
         }
       },
       {
         "type": "rect",
         "interactive": false,
         "encode": {
           "enter": {
             "y": {"value": 0},
             "height": {"value": 70},
             "width": {"value": 1},
             "fill": {"value": "firebrick"}
           },
           "update": {
             "x": {"signal": "brush[0]"}
           }
         }
       },
       {
         "type": "rect",
         "interactive": false,
         "encode": {
           "enter": {
             "y": {"value": 0},
             "height": {"value": 70},
             "width": {"value": 1},
             "fill": {"value": "firebrick"}
           },
           "update": {
             "x": {"signal": "brush[1]"}
           }
         }
       }
     ]
   }
 ]

} </graph>

Extension:Graph/Demo/IndexChart From https://vega.github.io/editor/#/examples/vega/stock-index-chart <graph mode=interactive title="Stock Market"> {

 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "description": "An interactive line chart of stock prices, with returns shown relative to a selected date.",
 "width": 650,
 "height": 300,
 "padding": 5,
 "autosize": {"type": "fit", "contains": "padding"},
 "signals": [
   {
     "name": "indexDate",
     "update": "time('Jan 1 2005')",
     "on": [
       {
         "events": "mousemove",
         "update": "invert('x', clamp(x(), 0, width))"
       }
     ]
   },
   {
     "name": "maxDate",
     "update": "time('Mar 1 2010')"
   }
 ],
 "data": [
   {
     "name": "stocks",
     "url": "https://www.mediawiki.org/wiki/Extension:Graph/data/stocks-csv?action=raw",
     "format": {"type": "csv", "parse": {"price":"number", "date":"date"}}
   },
   {
     "name": "index",
     "source": "stocks",
     "transform": [
       {
         "type": "filter",
         "expr": "month(datum.date) == month(indexDate) && year(datum.date) == year(indexDate)"
       }
     ]
   },
   {
     "name": "indexed_stocks",
     "source": "stocks",
     "transform": [
       {
         "type": "lookup", "from": "index", "key": "symbol",
         "fields": ["symbol"], "as": ["index"], "default": {"price": 0}
       },
       {
         "type": "formula",
         "as": "indexed_price",
         "expr": "datum.index.price > 0 ? (datum.price - datum.index.price)/datum.index.price : 0"
       }
     ]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "time",
     "domain": {"data": "stocks", "field": "date"},
     "range": "width"
   },
   {
     "name": "y",
     "type": "linear",
     "domain": {"data": "indexed_stocks", "field": "indexed_price"},
     "nice": true, "zero": true,
     "range": "height"
   },
   {
     "name": "color",
     "type": "ordinal",
     "range": "category",
     "domain": {"data": "stocks", "field": "symbol"}
   }
 ],
 "axes": [
   {"orient": "left", "scale": "y", "grid": true, "format": "%"}
 ],
 "marks": [
   {
     "type": "group",
     "from": {
       "facet": {
         "name": "series",
         "data": "indexed_stocks",
         "groupby": "symbol"
       }
     },
     "data": [
       {
         "name": "label",
         "source": "series",
         "transform": [
           { "type": "filter", "expr": "datum.date == maxDate" }
         ]
       }
     ],
     "marks": [
       {
         "type": "line",
         "from": {"data": "series"},
         "encode": {
           "update": {
             "x": {"scale": "x", "field": "date"},
             "y": {"scale": "y", "field": "indexed_price"},
             "stroke": {"scale": "color", "field": "symbol"},
             "strokeWidth": {"value": 2}
           }
         }
       },
       {
         "type": "text",
         "from": {"data": "label"},
         "encode": {
           "update": {
             "x": {"scale": "x", "field": "date", "offset": 2},
             "y": {"scale": "y", "field": "indexed_price"},
             "fill": {"scale": "color", "field": "symbol"},
             "text": {"field": "symbol"},
             "baseline": {"value": "middle"}
           }
         }
       }
     ]
   },
   {
     "type": "rule",
     "encode": {
       "update": {
         "x": {"field": {"group": "x"}},
         "x2": {"field": {"group": "width"}},
         "y": {"value": 0.5, "offset": {"scale": "y", "value": 0, "round": true}},
         "stroke": {"value": "black"},
         "strokeWidth": {"value": 1}
       }
     }
   },
   {
     "type": "rule",
     "encode": {
       "update": {
         "x": {"scale": "x", "signal": "indexDate", "offset": 0.5},
         "y": {"value": 0},
         "y2": {"field": {"group": "height"}},
         "stroke": {"value": "firebrick"}
       }
     }
   },
   {
     "type": "text",
     "encode": {
       "update": {
         "x": {"scale": "x", "signal": "indexDate"},
         "y2": {"field": {"group": "height"}, "offset": 15},
         "align": {"value": "center"},
         "text": {"signal": "timeFormat(indexDate, '%b %Y')"},
         "fill": {"value": "firebrick"}
       }
     }
   }
 ]

} </graph>

Using RESTBase API

Show pageview graphs for a range of dates, using pageview analytics API. See Template:Graph:PageViews .

Current page and en.wikipedia.org's main page for the last 30 days

{{Template:Graph:PageViews}}
{{Template:Graph:PageViews|30|Main Page|en.wikipedia.org}}

<graph> {

 //
 // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:PageViews
 //            Please do not modify it anywhere else, as it may get copied and override your changes.
 //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:PageViews
 //            The graph uses PageViews API https://wikitech.wikimedia.org/wiki/Analytics/AQS/Pageviews
 //
 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "width": 800,
 "height": 200,
 "autosize": {
   "type": "fit",
   "resize": false,
   "contains": "padding"
 },
 // The data for this graph comes from the PageView API.  The request is made for N days back up to now.
 "data": [
   {
     "name": "pageviews",
     "url": "https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/www.linuxwebexpert.com/all-access/user/Extension%3AGraph%2FDemo/daily/2024112500/2024122500",
     "format": {
       "type": "json",
       "property": "items"
     },
     // The response is parsed here, converting date strings of form "20160223" into date 2016-02-23
     "transform": [
       { "type": "formula", "as": "year", "expr": "parseInt(substring(datum.timestamp,0,4))" },
       { "type": "formula", "as": "month", "expr": "parseInt(substring(datum.timestamp,4,6))" },
       { "type": "formula", "as": "day", "expr": "parseInt(substring(datum.timestamp,6,8))" },
       { "type": "formula", "as": "date", "expr": "datetime(datum.year,datum.month-1,datum.day)" }
     ]
   }
 ],
 "scales": [
   // The dates are scaled to the "x" axis - the width of the graph
   {
     "name": "x",
     "type": "time",
     "range": "width",
     "domain": {"data": "pageviews","fields": ["date"]}
   },
   // The pageviews are scaled to the "y" axis - the height of the graph
   // Optional scale parameter can change "linear" to other scales like log
   // Optional max parameter can fix the upper bound of the graph
   {
     "name": "y",
     "type": "linear",
     "range": "height",
     "domain": {"data": "pageviews","fields": ["views"]},
     "clamp": true,
     "nice": true
   }
 ],
 // Simple axis with horizontal grid lines
 "axes": [
   {
     "orient": "bottom",
     "scale": "x",
     "tickCount": 5
   },
   {
     "orient": "left",
     "scale": "y",
     "grid": true,
     "tickCount": 5
   }
 ],
 // The graph is drawn with two elements a thick line at the top, and a semi-transparent area below
 "marks": [
   {
     "type": "line",
     "from": {"data": "pageviews"},
     "encode": {
       "enter": {
         "x": {"scale": "x","field": "date"},
         "y": {"scale": "y","field": "views"},
         "stroke": {"value": "#36c"},
         "strokeWidth": {"value": 3},
         "interpolate": {"value": "monotone"}
       }
     }
   },
   {
     "type": "area",
     "from": {"data": "pageviews"},
     "encode": {
       "enter": {
         "x": {"scale": "x","field": "date"},
         "y": {"scale": "y","value": 0},
         "y2": {"scale": "y","field": "views"},
         "fill": {"value": "#36c"},
         "fillOpacity": {"value": 0.35},
         "interpolate": {"value": "monotone"}
       }
     }
   }
 ],
 "config": {
   "axis": {
     "labelColor": "#54595d",
     "tickColor": "#54595d",
     "tickWidth": 1.5,
     "gridColor": "#a2a9b1",
     "gridOpacity": 0.4,
     "gridWidth": 2,
     "domainWidth": 2
   }
 }

} </graph> <graph> {

 //
 // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:PageViews
 //            Please do not modify it anywhere else, as it may get copied and override your changes.
 //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:PageViews
 //            The graph uses PageViews API https://wikitech.wikimedia.org/wiki/Analytics/AQS/Pageviews
 //
 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "width": 800,
 "height": 200,
 "autosize": {
   "type": "fit",
   "resize": false,
   "contains": "padding"
 },
 // The data for this graph comes from the PageView API.  The request is made for N days back up to now.
 "data": [
   {
     "name": "pageviews",
     "url": "https://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia.org/all-access/user/Main%20Page/daily/2024112500/2024122500",
     "format": {
       "type": "json",
       "property": "items"
     },
     // The response is parsed here, converting date strings of form "20160223" into date 2016-02-23
     "transform": [
       { "type": "formula", "as": "year", "expr": "parseInt(substring(datum.timestamp,0,4))" },
       { "type": "formula", "as": "month", "expr": "parseInt(substring(datum.timestamp,4,6))" },
       { "type": "formula", "as": "day", "expr": "parseInt(substring(datum.timestamp,6,8))" },
       { "type": "formula", "as": "date", "expr": "datetime(datum.year,datum.month-1,datum.day)" }
     ]
   }
 ],
 "scales": [
   // The dates are scaled to the "x" axis - the width of the graph
   {
     "name": "x",
     "type": "time",
     "range": "width",
     "domain": {"data": "pageviews","fields": ["date"]}
   },
   // The pageviews are scaled to the "y" axis - the height of the graph
   // Optional scale parameter can change "linear" to other scales like log
   // Optional max parameter can fix the upper bound of the graph
   {
     "name": "y",
     "type": "linear",
     "range": "height",
     "domain": {"data": "pageviews","fields": ["views"]},
     "clamp": true,
     "nice": true
   }
 ],
 // Simple axis with horizontal grid lines
 "axes": [
   {
     "orient": "bottom",
     "scale": "x",
     "tickCount": 5
   },
   {
     "orient": "left",
     "scale": "y",
     "grid": true,
     "tickCount": 5
   }
 ],
 // The graph is drawn with two elements a thick line at the top, and a semi-transparent area below
 "marks": [
   {
     "type": "line",
     "from": {"data": "pageviews"},
     "encode": {
       "enter": {
         "x": {"scale": "x","field": "date"},
         "y": {"scale": "y","field": "views"},
         "stroke": {"value": "#36c"},
         "strokeWidth": {"value": 3},
         "interpolate": {"value": "monotone"}
       }
     }
   },
   {
     "type": "area",
     "from": {"data": "pageviews"},
     "encode": {
       "enter": {
         "x": {"scale": "x","field": "date"},
         "y": {"scale": "y","value": 0},
         "y2": {"scale": "y","field": "views"},
         "fill": {"value": "#36c"},
         "fillOpacity": {"value": 0.35},
         "interpolate": {"value": "monotone"}
       }
     }
   }
 ],
 "config": {
   "axis": {
     "labelColor": "#54595d",
     "tickColor": "#54595d",
     "tickWidth": 1.5,
     "gridColor": "#a2a9b1",
     "gridOpacity": 0.4,
     "gridWidth": 2,
     "domainWidth": 2
   }
 }

} </graph>

Current page and en.wikipedia main page for the last 30 days - per type <graph>{

 "version": 2,
 "width": 400,
 "height": 200,
 "data": [
   {
     "name": "pv-desktop",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/mediawiki/desktop/user/Extension%3AGraph%2FDemo/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "pv-mobileweb",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/mediawiki/mobile-web/user/Extension%3AGraph%2FDemo/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "pv-mobileapp",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/mediawiki/mobile-app/user/Extension%3AGraph%2FDemo/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "alldata",
     "source": "pv-desktop",
     "transform": [
       {
         "type": "formula",
         "field": "Desktop",
         "expr": "datum.views"
       },
       {
         "type": "lookup",
         "on": "pv-mobileweb",
         "onKey": "date",
         "keys": ["date"],
         "as": ["mobilecount"]
       },
       {
         "type": "formula",
         "field": "Mobile",
         "expr": "datum.mobilecount.views"
       },
       {
         "type": "lookup",
         "on": "pv-mobileapp",
         "onKey": "date",
         "keys": ["date"],
         "as": ["appcount"]
       },
       {
         "type": "formula",
         "field": "App",
         "expr": "datum.appcount.views"
       },
       {"type": "fold", "fields": ["Desktop", "Mobile", "App"]}
     ]
   },
   {
     "name": "stats",
     "source": "alldata",
     "transform": [
       {
         "type": "aggregate",
         "groupby": ["date"],
         "summarize": [{"field": "value", "ops": ["sum"]}]
       }
     ]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "time",
     "range": "width",
     "domain": {"data": "alldata","field": "date"}
   },
   {
     "name": "y",
     "type": "linear",
     "range": "height",
     "nice": true,
     "domain": {"data": "stats", "field": "sum_value"}
   },
   {
     "name": "c",
     "type": "ordinal",
     "range": ["#B2912F","#5DA5DA","#FAA43A"],
     "domain": {"data": "alldata", "field": "key"}
   }
 ],
 "axes": [
   {"type": "x","scale": "x","ticks": 5},
   {"type": "y","scale": "y"}
 ],
 "legends": [
   {"fill": "c"}
 ],
 "marks": [
   {
     "type": "group",
     "from": {
       "data": "alldata",
       "transform": [
         {"type": "stack", "groupby": ["date"], "sortby": ["key"], "field": "value"},
         {"type": "facet", "groupby": ["key"]}
       ]
     },
     "marks": [
       {
         "type": "area",
         "properties": {
           "enter": {
             "interpolate": {"value": "monotone"},
             "x": {"scale": "x", "field": "date"},
             "y": {"scale": "y", "field": "layout_start"},
             "y2": {"scale": "y", "field": "layout_end"},
             "fill": {"scale": "c", "field": "key"},
             "fillOpacity": {"value": 1}
           }
         }
       }
     ]
   }
 ]

}</graph> <graph>{

 "version": 2,
 "width": 400,
 "height": 200,
 "data": [
   {
     "name": "pv-desktop",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia/desktop/user/Main_Page/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "pv-mobileweb",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia/mobile-web/user/Main_Page/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "pv-mobileapp",
     "url": "wikirest://wikimedia.org/api/rest_v1/metrics/pageviews/per-article/en.wikipedia/mobile-app/user/Main_Page/daily/2024112506/2024122506",
     "format": {"type": "json","property": "items"},
     "transform": [
       {
         "type": "formula",
         "field": "date",
         "expr": "datetime(parseInt(substring(datum.timestamp,0,4)),parseInt(substring(datum.timestamp,4,6))-1,parseInt(substring(datum.timestamp,6,8)))"
       }
     ]
   },
   {
     "name": "alldata",
     "source": "pv-desktop",
     "transform": [
       {
         "type": "formula",
         "field": "Desktop",
         "expr": "datum.views"
       },
       {
         "type": "lookup",
         "on": "pv-mobileweb",
         "onKey": "date",
         "keys": ["date"],
         "as": ["mobilecount"]
       },
       {
         "type": "formula",
         "field": "Mobile",
         "expr": "datum.mobilecount.views"
       },
       {
         "type": "lookup",
         "on": "pv-mobileapp",
         "onKey": "date",
         "keys": ["date"],
         "as": ["appcount"]
       },
       {
         "type": "formula",
         "field": "App",
         "expr": "datum.appcount.views"
       },
       {"type": "fold", "fields": ["Desktop", "Mobile", "App"]}
     ]
   },
   {
     "name": "stats",
     "source": "alldata",
     "transform": [
       {
         "type": "aggregate",
         "groupby": ["date"],
         "summarize": [{"field": "value", "ops": ["sum"]}]
       }
     ]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "time",
     "range": "width",
     "domain": {"data": "alldata","field": "date"}
   },
   {
     "name": "y",
     "type": "linear",
     "range": "height",
     "nice": true,
     "domain": {"data": "stats", "field": "sum_value"}
   },
   {
     "name": "c",
     "type": "ordinal",
     "range": ["#B2912F","#5DA5DA","#FAA43A"],
     "domain": {"data": "alldata", "field": "key"}
   }
 ],
 "axes": [
   {"type": "x","scale": "x","ticks": 5},
   {"type": "y","scale": "y"}
 ],
 "legends": [
   {"fill": "c"}
 ],
 "marks": [
   {
     "type": "group",
     "from": {
       "data": "alldata",
       "transform": [
         {"type": "stack", "groupby": ["date"], "sortby": ["key"], "field": "value"},
         {"type": "facet", "groupby": ["key"]}
       ]
     },
     "marks": [
       {
         "type": "area",
         "properties": {
           "enter": {
             "interpolate": {"value": "monotone"},
             "x": {"scale": "x", "field": "date"},
             "y": {"scale": "y", "field": "layout_start"},
             "y2": {"scale": "y", "field": "layout_end"},
             "fill": {"scale": "c", "field": "key"},
             "fillOpacity": {"value": 1}
           }
         }
       }
     ]
   }
 ]

}</graph>

Using MediaWiki API

This graph shows edit history for a wiki page. See {{Graph:PageHistory}}.

Current Page Albert Einstein from en.wikipedia.org
<graph>

{

 //
 // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:PageHistory
 //            Please do not modify it anywhere else, as it may get copied and override your changes.
 //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:PageHistory
 //            The graph uses Query API https://www.mediawiki.org/w/api.php?action=help&modules=query%2Brevisions
 //
 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "width": 500,
 "height": 300,
 "autosize": {
   "type": "fit",
   "resize": false,
   "contains": "padding"
 },
 // Loads last max (500) revisions of the given (or current) article
 "data": [
   {
     "name": "values",
     "url": "https://www.mediawiki.org/w/api.php?action=query&format=json&formatversion=2&prop=revisions&titles=Extension%3AGraph%2FDemo&rvlimit=max&rvprop=timestamp%7Cuser%7Csize&rawcontinue",
     "format": {
       "type": "json",
       "property": "query.pages.[0].revisions",
       "parse": {"user":"string", "timestamp": "date", "size": "number"}
     },
   },
   {
     "name": "stats",
     "source": "values",
     "transform": [{"type": "aggregate", "groupby": ["timestamp"], "fields": ["size"], "ops": ["sum"]}]
   }
 ],
 "scales": [
 {
   "name": "x",
   "type": "time",
   "range": "width",
   "domain": {"data": "values","fields": ["timestamp"]}
 },
 {
   "name": "y",
   "type": "linear",
   "range": "height",
   "nice": true,
   "domain": {"data": "stats","fields": ["sum_size"]}
 },
 {
   "name": "color",
   "type": "ordinal",
   "range": {"scheme": "category20"},
   "domain": {"data": "values","fields": ["user"]}
 }],
 "axes": [
 {
   "orient": "bottom",
   "scale": "x",
   "tickOffset": 0,
   "grid": true,
   "subdivide": 2,
   "encode": {
     "ticks": { "update": {"stroke": {"value": "#666666"} } },
     "labels": { "update": {"fill": {"value": "#666666"},"angle": {"value": 30},"align": {"value": "left"} } },
     "grid": { "update": {"stroke": {"value": "#cacaca"} } },
     "axis": { "update": {"stroke": {"value": "#666666"},"strokeWidth": {"value": 2} } }
   }
 },
 {
   "orient": "left",
   "scale": "y",
   "grid": true,
   "title": "Page size (bytes)",
   "encode": {
     "ticks": { "update": {"stroke": {"value": "#666666"} } },
     "labels": { "update": {"fill": {"value": "#666666"} } },
     "grid": { "update": {"stroke": {"value": "#cacaca"} } },
     "axis": { "update": {"stroke": {"value": "#666666"},"strokeWidth": {"value": 2} } }
   }
 }],
 "legends": [{
   "fill": "color",
   "title": "User",
   "offset": 10,
   "properties": {"symbols": {"stroke": {"value": "transparent"} } }
 }],
 "marks": [
 {
   "type": "line",
   "from": {"data": "values"},
   "encode": {
     "enter": {
       "x": {"scale": "x","field": "timestamp"},
       "y": {"scale": "y","field": "size"},
       "stroke": {"value": "#000"},
       "strokeWidth": {"value": 1}
     }
   }
 },
 {
   "type": "symbol",
   "from": {"data": "values"},
   "encode": {
     "enter": {
       "x": {"scale": "x","field": "timestamp"},
       "y": {"scale": "y","field": "size"},  
       "fill": {"scale": "color", "field": "user"},
       "size": {"value": 15},
       "stroke": {"scale": "color", "field": "user"}
     }
   }
 }]

}

</graph>
<graph>

{

 //
 // ATTENTION: This code is maintained at https://www.mediawiki.org/wiki/Template:Graph:PageHistory
 //            Please do not modify it anywhere else, as it may get copied and override your changes.
 //            Suggestions can be made at https://www.mediawiki.org/wiki/Template_talk:Graph:PageHistory
 //            The graph uses Query API https://www.mediawiki.org/w/api.php?action=help&modules=query%2Brevisions
 //
 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "width": 500,
 "height": 300,
 "autosize": {
   "type": "fit",
   "resize": false,
   "contains": "padding"
 },
 // Loads last max (500) revisions of the given (or current) article
 "data": [
   {
     "name": "values",
     "url": "https://en.wikipedia.org/w/api.php?action=query&format=json&formatversion=2&prop=revisions&titles=Albert+Einstein&rvlimit=max&rvprop=timestamp%7Cuser%7Csize&rawcontinue",
     "format": {
       "type": "json",
       "property": "query.pages.[0].revisions",
       "parse": {"user":"string", "timestamp": "date", "size": "number"}
     },
   },
   {
     "name": "stats",
     "source": "values",
     "transform": [{"type": "aggregate", "groupby": ["timestamp"], "fields": ["size"], "ops": ["sum"]}]
   }
 ],
 "scales": [
 {
   "name": "x",
   "type": "time",
   "range": "width",
   "domain": {"data": "values","fields": ["timestamp"]}
 },
 {
   "name": "y",
   "type": "linear",
   "range": "height",
   "nice": true,
   "domain": {"data": "stats","fields": ["sum_size"]}
 },
 {
   "name": "color",
   "type": "ordinal",
   "range": {"scheme": "category20"},
   "domain": {"data": "values","fields": ["user"]}
 }],
 "axes": [
 {
   "orient": "bottom",
   "scale": "x",
   "tickOffset": 0,
   "grid": true,
   "subdivide": 2,
   "encode": {
     "ticks": { "update": {"stroke": {"value": "#666666"} } },
     "labels": { "update": {"fill": {"value": "#666666"},"angle": {"value": 30},"align": {"value": "left"} } },
     "grid": { "update": {"stroke": {"value": "#cacaca"} } },
     "axis": { "update": {"stroke": {"value": "#666666"},"strokeWidth": {"value": 2} } }
   }
 },
 {
   "orient": "left",
   "scale": "y",
   "grid": true,
   "title": "Page size (bytes)",
   "encode": {
     "ticks": { "update": {"stroke": {"value": "#666666"} } },
     "labels": { "update": {"fill": {"value": "#666666"} } },
     "grid": { "update": {"stroke": {"value": "#cacaca"} } },
     "axis": { "update": {"stroke": {"value": "#666666"},"strokeWidth": {"value": 2} } }
   }
 }],
 "legends": [{
   "fill": "color",
   "title": "User",
   "offset": 10,
   "properties": {"symbols": {"stroke": {"value": "transparent"} } }
 }],
 "marks": [
 {
   "type": "line",
   "from": {"data": "values"},
   "encode": {
     "enter": {
       "x": {"scale": "x","field": "timestamp"},
       "y": {"scale": "y","field": "size"},
       "stroke": {"value": "#000"},
       "strokeWidth": {"value": 1}
     }
   }
 },
 {
   "type": "symbol",
   "from": {"data": "values"},
   "encode": {
     "enter": {
       "x": {"scale": "x","field": "timestamp"},
       "y": {"scale": "y","field": "size"},  
       "fill": {"scale": "color", "field": "user"},
       "size": {"value": 15},
       "stroke": {"scale": "color", "field": "user"}
     }
   }
 }]

}

</graph>

This graph shows the number of pages in each subcategory. See graph source code.

Category:Extensions by category. Category:People from en.wikipedia.org
<graph>

{

 "version": 2,
 "width": 300,
 "height": 300,
 "data": [
   {
     // Data is retrieved from the MediaWiki API.  By default it uses current wiki's "Extension by category"
     "name": "table",
     "url": "wikiapi:///?generator=categorymembers&gcmtitle=Category:Extensions+by+category&gcmtype=subcat&action=query&gcmlimit=max&prop=categoryinfo&formatversion=2&format=json",
     // We are only interested in the content of query.pages subelement.
     "format": {"property": "query.pages","type": "json"},
     "transform": [
       // sort in descending order using category size as the sort key
       {"type": "sort","by": "-categoryinfo.size"},
       // To visualize, use "pie" transformation to add layout_start, layout_end, and layout_mid fields to each page object
       // These fields contain angles at which to start and stop drawing arcs. First element's start will be 0, and last element's end will be 360 degrees (in radians)
       {"type": "pie","field": "categoryinfo.size"}
     ]
   }
 ],
 // Scales are like functions -- marks use them to convert a data value into a visual value, like x or y coordinate on the graph, or a color value.
 "scales": [
   {
     // This scale will be used to assign a color to each slice, using a palette of 10 colors
     "name": "color",
     "domain": {"data": "table","field": "title"},
     "range": "category10",
     "type": "ordinal"
   }
 ],
 "marks": [
   {
     // This mark draws the actual pie chart from the data source
     // Each element is an arc between layout_start and layout_end angles (as calculated by the pie transformation)
     // drawn with a given radius, stroke, and fill.
     "from": {"data": "table"},
     "type": "arc",
     "properties": {
       "enter": {
         "fill": {"scale": "color","field": "title"},
         "outerRadius": {"value": 200},
         "startAngle": {"field": "layout_start"},
         "endAngle": {"field": "layout_end"},
         "stroke": {"value": "white"},
         "strokeWidth": {"value": 1}
       }
     }
   },
   {
     // This mark draws labels around the pie chart after the pie chart has been drawn
     "type": "text",
     // Before drawing, we need to perform a number of calculations to figure out the exact location and orientation of the text
     "from": {
       "data": "table",
       "transform": [
         // For each data point (datum), each of these transformations will be ran in order.
         // Formula transformation evaluates the expression and assigns result to the datapoint
         // Size of the pie slice, in degrees:  sliceSize = (end - start) * 180 / Pi
         { "type": "formula", "field": "sliceSize", "expr": "(datum.layout_end - datum.layout_start)*180/PI" },
         // Draw text only if the slice of the arc is more than 2 degrees to avoid overcrowding
         { "type": "filter", "test": "datum.sliceSize > 2" },
         // Remove namespace from the text - keeps only text after the first ':' symbol, limits to 40 chars.
         { "type": "formula", "field": "title", "expr": "substring(datum.title, 1+indexof(datum.title,':'), 40)" },
         // Determine the side of the pie chart we are on - left or right.
         { "type": "formula", "field": "invert", "expr": "datum.layout_mid*180/PI < 180 ? 1 : -1" },
         // If on the left, the text should be right-aligned (go from the rim inward)
         { "type": "formula", "field": "align", "expr": "datum.invert < 0 ? 'left' : 'right'" },
         // At what angle should the text be drawn relative to the point on the circle
         { "type": "formula", "field": "angle", "expr": "(datum.layout_mid*180/PI)-90*datum.invert" },
         // Make font smaller for smaller pie slices
         { "type": "formula", "field": "fontSize", "expr": "datum.sliceSize > 20 ? 15 : (datum.sliceSize > 10 ? 14 : 10)" },
         // Make font bold for largest pie slices 
         { "type": "formula", "field": "fontWeight", "expr": "datum.sliceSize > 15 ? 'bold' : 'normal'" }
       ]
     },
     "properties": {
       "enter": {
         // Use the fields calculated in the transformation to draw category names
         "align": {"field": "align"},
         "angle": {"field": "angle"},
         "baseline": {"value": "middle"},
         "fill": {"value": "black"},
         "fontSize": {"field": "fontSize"},
         "fontWeight": {"field": "fontWeight"},
         "radius": {"value": 270},
         "text": {"field": "title"},
         "theta": {"field": "layout_mid"}
       }
     }
   }
 ]

} </graph>

<graph>

{

 "version": 2,
 "width": 300,
 "height": 300,
 "data": [
   {
     // Data is retrieved from the MediaWiki API.  By default it uses current wiki's "Extension by category"
     "name": "table",
     "url": "wikiapi://en.wikipedia.org/?generator=categorymembers&gcmtitle=Category:People&gcmtype=subcat&action=query&gcmlimit=max&prop=categoryinfo&formatversion=2&format=json",
     // We are only interested in the content of query.pages subelement.
     "format": {"property": "query.pages","type": "json"},
     "transform": [
       // sort in descending order using category size as the sort key
       {"type": "sort","by": "-categoryinfo.size"},
       // To visualize, use "pie" transformation to add layout_start, layout_end, and layout_mid fields to each page object
       // These fields contain angles at which to start and stop drawing arcs. First element's start will be 0, and last element's end will be 360 degrees (in radians)
       {"type": "pie","field": "categoryinfo.size"}
     ]
   }
 ],
 // Scales are like functions -- marks use them to convert a data value into a visual value, like x or y coordinate on the graph, or a color value.
 "scales": [
   {
     // This scale will be used to assign a color to each slice, using a palette of 10 colors
     "name": "color",
     "domain": {"data": "table","field": "title"},
     "range": "category10",
     "type": "ordinal"
   }
 ],
 "marks": [
   {
     // This mark draws the actual pie chart from the data source
     // Each element is an arc between layout_start and layout_end angles (as calculated by the pie transformation)
     // drawn with a given radius, stroke, and fill.
     "from": {"data": "table"},
     "type": "arc",
     "properties": {
       "enter": {
         "fill": {"scale": "color","field": "title"},
         "outerRadius": {"value": 200},
         "startAngle": {"field": "layout_start"},
         "endAngle": {"field": "layout_end"},
         "stroke": {"value": "white"},
         "strokeWidth": {"value": 1}
       }
     }
   },
   {
     // This mark draws labels around the pie chart after the pie chart has been drawn
     "type": "text",
     // Before drawing, we need to perform a number of calculations to figure out the exact location and orientation of the text
     "from": {
       "data": "table",
       "transform": [
         // For each data point (datum), each of these transformations will be ran in order.
         // Formula transformation evaluates the expression and assigns result to the datapoint
         // Size of the pie slice, in degrees:  sliceSize = (end - start) * 180 / Pi
         { "type": "formula", "field": "sliceSize", "expr": "(datum.layout_end - datum.layout_start)*180/PI" },
         // Draw text only if the slice of the arc is more than 2 degrees to avoid overcrowding
         { "type": "filter", "test": "datum.sliceSize > 2" },
         // Remove namespace from the text - keeps only text after the first ':' symbol, limits to 40 chars.
         { "type": "formula", "field": "title", "expr": "substring(datum.title, 1+indexof(datum.title,':'), 40)" },
         // Determine the side of the pie chart we are on - left or right.
         { "type": "formula", "field": "invert", "expr": "datum.layout_mid*180/PI < 180 ? 1 : -1" },
         // If on the left, the text should be right-aligned (go from the rim inward)
         { "type": "formula", "field": "align", "expr": "datum.invert < 0 ? 'left' : 'right'" },
         // At what angle should the text be drawn relative to the point on the circle
         { "type": "formula", "field": "angle", "expr": "(datum.layout_mid*180/PI)-90*datum.invert" },
         // Make font smaller for smaller pie slices
         { "type": "formula", "field": "fontSize", "expr": "datum.sliceSize > 20 ? 15 : (datum.sliceSize > 10 ? 14 : 10)" },
         // Make font bold for largest pie slices 
         { "type": "formula", "field": "fontWeight", "expr": "datum.sliceSize > 15 ? 'bold' : 'normal'" }
       ]
     },
     "properties": {
       "enter": {
         // Use the fields calculated in the transformation to draw category names
         "align": {"field": "align"},
         "angle": {"field": "angle"},
         "baseline": {"value": "middle"},
         "fill": {"value": "black"},
         "fontSize": {"field": "fontSize"},
         "fontWeight": {"field": "fontWeight"},
         "radius": {"value": 270},
         "text": {"field": "title"},
         "theta": {"field": "layout_mid"}
       }
     }
   }
 ]

} </graph>

Using Wikidata Query Service API

See more examples.

<graph mode="interactive"> {

 "version": 2, "width": 650, "height": 270, "padding": 12, "background": "#edf1f7",
 "data": [{
     "name": "map",
     "url": "wikiraw:///Extension:Graph/Demo/RawData:WorldMap-json",
     "format": {"type": "topojson","feature": "countries"},
     "transform": [
       {
         "type": "geopath",
         "value": "data",
         "scale": 80,
         "center": [-180,125],
         "translate": [0,0],
         "projection": "equirectangular"
       }
     ]
   },
   
   {
     "name": "points",
     "url": "wikidatasparql:///?query=PREFIX%20wd%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fentity%2F%3E%0APREFIX%20wdt%3A%20%3Chttp%3A%2F%2Fwww.wikidata.org%2Fprop%2Fdirect%2F%3E%0APREFIX%20wikibase%3A%20%3Chttp%3A%2F%2Fwikiba.se%2Fontology%23%3E%0APREFIX%20xsd%3A%20%3Chttp%3A%2F%2Fwww.w3.org%2F2001%2FXMLSchema%23%3E%0A%0ASELECT%20%3Fevent%20(MIN(%3FrowAffected)%20as%20%3Faffected)%20(SAMPLE(%3FclassName)%20as%20%3Fclass)%20%3Fgps%0AWHERE%20%0A%7B%0A%20%20%7B%0A%20%20%20%20%3Fevt%20wdt%3AP31%20%3Fclass%20.%0A%20%20%20%20%3Fclass%20wdt%3AP279*%20wd%3AQ3839081%20.%0A%20%20%7D%0A%20%20OPTIONAL%20%7B%20%3Fevt%20wdt%3AP1590%20%3Fcasualties%20%7D%20.%0A%20%20OPTIONAL%20%7B%20%3Fevt%20wdt%3AP1120%20%3Fdeaths%20%7D%20.%0A%20%20OPTIONAL%20%7B%20%3Fevt%20wdt%3AP1446%20%3Fmissing%20%7D%20.%0A%20%20OPTIONAL%20%7B%20%3Fevt%20wdt%3AP1339%20%3Finjured%20%7D%20.%0A%20%20BIND(COALESCE(%3Fcasualties%2C0)%20%2B%20COALESCE(%3Fdeaths%2C0)%20%2B%20COALESCE(%3Fmissing%2C0)%20%2B%20COALESCE(%3Finjured%2C0)%20as%20%3FrowAffected)%0A%20%20FILTER%20(%3FrowAffected%20%3E%200)%20%0A%20%20%3Fevt%20wdt%3AP625%20%3Fgps%20.%0A%20%20SERVICE%20wikibase%3Alabel%20%7B%0A%20%20%20%20bd%3AserviceParam%20wikibase%3Alanguage%20%22en%22%20.%0A%20%20%20%20%3Fclass%20rdfs%3Alabel%20%3FclassName%20.%0A%20%20%20%20%3Fevt%20rdfs%3Alabel%20%3Fevent%20.%0A%20%20%7D%0A%7D%0AGROUP%20BY%20%3Fevent%20%3Fgps%20%0AORDER%20BY%20DESC(%3Faffected)%0ALIMIT%201000%0A",
     "format": {
       "type": "json"
     },
     "transform": [
     	{"type": "sort", "by": "-affected"},
       {
         "type": "geo",
         "projection": "equirectangular",
         "scale": 80,
         "center": [-180,125],
         "translate": [0,0],
         "lon": "gps[0]",
         "lat": "gps[1]"
       }
     ]
   }
 ],
 "signals": [
   {
     "name": "mouseoverSignal",
     "init": null,
     "streams": [
       {  
         "type": "@circle:mouseover",
         "expr": "eventItem().datum"
       },
       {
         "type": "@circle:mouseout",
         "expr": null
       }
     ]
   }
 ],
 "scales": [
   {
     "name": "size",
     "type": "linear",
     "domain": {"data": "points", "field": "affected"},
     "range": [16, 1000]
   },
   {
     "name": "class",
     "type": "ordinal",
     "domain": {"data": "points", "field": "class"},
     "range": "category20"
   }
 ],
 "marks": [
   {
     "type": "text",
     "properties": {
       "enter": {
         "text": {"value": "Disasters"},
         "x": {"value": 0},
         "y": {"value": 25},
         "fontSize": {"value": 32},
         "fontWeight": {"value": "bold"},
         "fill": {"value": "steelblue"}
       }
     }
   },
   {
     "name": "map",
     "type": "path",
     "from": {"data": "map"},
     "properties": {
       "enter": {
         "fill": {"value": "grey"},
         "path": {"field": "layout_path"}
       }
     }
   },
   {
     "name": "circle",
     "type": "symbol",
     "from": {"data": "points"},
     "properties": {
       "enter": {
         "size": {"scale": "size", "field": "affected"},
         "fill": {"scale": "class", "field": "class"},
         "fillOpacity": {"value": 0.8},
         "stroke": {"value": "white"},
         "strokeWidth": {"value": 0.5},
         "x": {"field": "layout_x"},
         "y": {"field": "layout_y"}
       }
     }
   },
   {
     "type": "text",
     "properties": {
       "enter": {
         "x": {"value": 500},
         "y": {"value": 10},
         "align": {"value": "right"},
         "fontSize": {"value": 17},
         "fill": {"value": "black"}
       },
       "update": {
         "text": [
           {
             "test": "mouseoverSignal !== null",
             "template": "\u007b{mouseoverSignal.event}\u007d: \u007b{mouseoverSignal.affected|number:'.2s'}\u007d"
           },
           { "value": "" } 
         ]
       }
     }
   }
 ],
 "legends": [
   {
     "fill": "class",
     "properties": {
       "labels": {
         "fontSize": {"value": 12}
       },
       "symbols": {
         "stroke": {"value": "transparent"}
       },
       "legend": {
         "x": {"value": 530},
         "y": {"value": -5}
       }
     }
   }
 ]

} </graph>

Trees

Cartesian tree

Extension:Graph/Demo/CartesianTree

<graph>{

 "version": 2,
 "width": 550,
 "height": 400,
 "data": [
   {
     "name": "tree",
     "url": "wikiraw:///Extension:Graph/data/flare-json",
     "format": {"type": "treejson"},
     "transform": [
       {"type": "hierarchy", "field": "size", "size": [400, 500]}
     ]
   }
 ],
 "marks": [
   {
     "type": "path",
     "from": {
       "data": "tree",
       "transform": [
         {
           "type": "filter", "test": "datum.parent"
         },
         {
           "type": "linkpath",
           "sourceX": "parent.layout_y",
           "sourceY": "parent.layout_x",
           "targetX": "layout_y",
           "targetY": "layout_x",
           "shape": "diagonalX"
         }
       ]
     },
     "properties": {
       "enter": {
         "path": {"field": "layout_path"},
         "stroke": {"value": "#ddd"}
       }
     }
   },
   {
     "type": "text",
     "from": {"data": "tree"},
     "properties": {
       "enter": {
         "x": {"field": "layout_y", "offset": -10},
         "y": {"field": "layout_x"},
         "font": {"value": "Helvetica Neue"},
         "fontSize": {"value": 10},
         "align": {"value": "left"},
         "baseline": {"value": "middle"},
         "fill": {"value": "#000"},
         "text": {"field": "name"}
       }
     }
   }
 ]

}</graph>

Radial tree

Extension:Graph/Demo/RadialTree

<graph>{

 "version": 2,
 "width": 600,
 "height": 600,
 "padding": 5,
 "signals": [
   { "name": "rotation", "init": 0,
     "streams": [{
       "type": "click",
       "expr": "rotation + 6.14/180"
     }]
   }
 ],
 "data": [
   {
     "name": "tree",
     "url": "wikiraw:///Extension:Graph/data/flare-json",
     "format": {"type": "treejson"},
     "transform": [
       { "type": "hierarchy", "sort": "name", "size": [6.28, 300], "orient": "radial", "output": {"x": "angle1", "y": "radius"} },
       { "type": "formula", "field": "angle",   "expr": "(datum.angle1 + rotation) % (2*PI)" },
       { "type": "formula", "field": "sign",    "expr": "datum.angle > 3.14 ? 1 : -1" },
       { "type": "formula", "field": "degrees", "expr": "!datum.radius ? 0 : (datum.angle + datum.sign*1.57) * 180/PI" },
       { "type": "formula", "field": "yy",      "expr": "300 + datum.radius * cos(datum.angle)" },
       { "type": "formula", "field": "xx",      "expr": "300 + datum.radius * -sin(datum.angle)" },
       { "type": "formula", "field": "align",   "expr": "!datum.radius ? 'center' : datum.sign < 0 ? 'left' : 'right'" }
     ]
   }
 ],
 "marks": [
   {
     "type": "path",
     "from": {
       "data": "tree",
       "transform": [
         {"type": "filter", "test": "datum.parent"},
         {
           "type": "linkpath",
           "sourceX": "parent.xx", "sourceY": "parent.yy",
           "targetX": "xx", "targetY": "yy",
           "shape": "line"
         }
       ]
     },
     "properties": {
       "update": {
         "path": {"field": "layout_path"},
         "stroke": {"value": "#ddd"}
       }
     }
   },
   {
     "type": "text",
     "from": {"data": "tree"},
     "properties": {
       "update": {
         "x": {"field": "xx"},
         "y": {"field": "yy"},
         "font": {"value": "Helvetica Neue"},
         "fontSize": {"value": 10},
         "align": {"field": "align"},
         "baseline": {"value": "middle"},
         "fill": {"value": "#000"},
         "text": {"field": "name"},
         "angle": {"field": "degrees"}
       }
     }
   }
 ]

}</graph>

Dendrogram

Extension:Graph/Demo/Dendrogram

<graph>{

 "width": 600,
 "height": 150,
 "background": "#ffffff",
 "data": [
   {
     "name": "tree",
     "values": [
       {"A": "Mammal","B": "Carnivore","C": "Panther" },
       {"A": "Mammal","B": "Carnivore","C": "Lion" },
       {"A": "Mammal","B": "Herbivore","C": "Cow" },
       {"A": "Mammal","B": "Herbivore","C": "Goat" },
       {"A": "Mammal","B": "Omnivore","C": "Human"},
       {"A": "Mammal","B": "Omnivore","C": "Bat"},
       {"A": "Fish","B": "Carnivore","C": "Shark"},
       {"A": "Fish","B": "Carnivore","C": "Electric Eel"},
       {"A": "Fish","B": "Omnivore","C": "Piranha "},
      {"A": "Fish","B": "Omnivore","C": "catfish "}
     ],
     "transform": [
       {
         "type": "treeify",
         "groupby": ["A","B"]
       },
       {
         "type": "hierarchy",
         "mode": "cluster",
         "nodesize": [20,100]
       },
       {
         "type": "formula",
         "field": "align",
         "expr": "'right'"
       },
       {
         "type": "formula",
         "field": "offset",
         "expr": "-10"
       }
     ]
   }
 ],
 "marks": [
   {
     "type": "path",
     "from": {
       "data": "tree",
       "transform": [
         {"type": "filter","test": "datum.parent"},
         {
           "type": "linkpath",
           "sourceX": "parent.layout_y",
           "sourceY": "parent.layout_x",
           "targetX": "layout_y",
           "targetY": "layout_x",
           "shape": "cornerX"
         }
       ]
     },
     "properties": {
       "enter": {
         "path": {"field": "layout_path"},
         "strokeWidth": {"value": 2},
         "stroke": {"value": "#000000"}
       }
     }
   },
   {
     "type": "text",
     "from": {
       "data": "tree",
       "transform": [
         {
           "type": "formula",
           "field": "ff_node_label",
           "expr": "if(datum.layout_depth == 0, 'Animals', if(datum.layout_depth == 1, datum.A, if(datum.layout_depth == 2, datum.B, if(datum.layout_depth == 3, datum.C, ))))"
         }
       ]
     },
     "properties": {
       "enter": {
         "x": {"field": "layout_y"},
         "dx": {"field": "offset"},
         "y": {"field": "layout_x"},
         "dy": {"value": -8},
         "font": {"value": "Arial"},
         "fontSize": {"value": 16},
         "align": {"field": "align"},
         "baseline": {"value": "middle"},
         "fill": {"value": "#0000ff"},
         "text": {"field": "ff_node_label"}
       }
     }
   }
 ]

}</graph>

Timeline / lifeline

<graph> {

 "$schema": "https://vega.github.io/schema/vega/v5.json",
 "width": 800,
 "height": 200,
 "autosize": {
   "type": "fit",
   "resize": false,
   "contains": "padding"
 },
 "data": [
   {
     "name": "people",
     "values": [
       {
         "label": "Washington",
         "born": -7506057600000,
         "died": -5366196000000,
         "enter": -5701424400000,
         "leave": -5453884800000
       },
       {
         "label": "Adams",
         "born": -7389766800000,
         "died": -4528285200000,
         "enter": -5453884800000,
         "leave": -5327740800000
       },
       {
         "label": "Jefferson",
         "born": -7154586000000,
         "died": -4528285200000,
         "enter": -5327740800000,
         "leave": -5075280000000
       },
       {
         "label": "Madison",
         "born": -6904544400000,
         "died": -4213184400000,
         "enter": -5075280000000,
         "leave": -4822819200000
       },
       {
         "label": "Monroe",
         "born": -6679904400000,
         "died": -4370518800000,
         "enter": -4822819200000,
         "leave": -4570358400000
       }
     ]
   },
   {
     "name": "events",
     "format": {
       "type": "json",
       "parse": {
         "when": "date"
       }
     },
     "values": [
       {
         "name": "Decl. of Independence",
         "when": -6106032422000
       },
       {
         "name": "U.S. Constitution",
         "when": -5706346022000
       },
       {
         "name": "Louisiana Purchase",
         "when": -5259744422000
       },
       {
         "name": "Monroe Doctrine",
         "when": -4609930022000
       }
     ]
   }
 ],
 "scales": [
   {
     "name": "y",
     "type": "band",
     "range": "height",
     "domain": {
       "data": "people",
       "fields": [
         "label"
       ]
     }
   },
   {
     "name": "x",
     "type": "time",
     "range": "width",
     "round": true,
     "domain": {
       "data": "people",
       "fields": [
           "born",
           "died"
       ]
     }
   }
 ],
 "axes": [
   {
     "encode": {
       "labels": {
         "update": {
           "fontSize": {
             "value": 18
           }
         }
       }
     },
     "scale": "x",
     "orient": "bottom"
   }
 ],
 "marks": [
   {
     "type": "text",
     "from": {
       "data": "events"
     },
     "encode": {
       "enter": {
         "x": {
           "scale": "x",
           "field": "when"
         },
         "y": {
           "value": -10
         },
         "angle": {
           "value": -25
         },
         "fill": {
           "value": "#000"
         },
         "text": {
           "field": "name"
         },
         "font": {
           "value": "Helvetica Neue"
         },
         "fontSize": {
           "value": 20
         }
       }
     }
   },
   {
     "type": "rect",
     "from": {
       "data": "events"
     },
     "encode": {
       "enter": {
         "x": {
           "scale": "x",
           "field": "when"
         },
         "y": {
           "value": -8
         },
         "width": {
           "value": 1
         },
         "height": {
           "field": {
             "group": "height"
           },
           "offset": 8
         },
         "fill": {
           "value": "#888"
         }
       }
     }
   },
   {
     "type": "text",
     "from": {
       "data": "people"
     },
     "encode": {
       "enter": {
         "x": {
           "scale": "x",
           "field": "born"
         },
         "y": {
           "scale": "y",
           "field": "label",
           "offset": -3
         },
         "fill": {
           "value": "#000"
         },
         "text": {
           "field": "label"
         },
         "font": {
           "value": "Helvetica Neue"
         },
         "fontSize": {
           "value": 20
         }
       }
     }
   },
   {
     "type": "rect",
     "from": {
       "data": "people"
     },
     "encode": {
       "enter": {
         "x": {
           "scale": "x",
           "field": "born"
         },
         "x2": {
           "scale": "x",
           "field": "died"
         },
         "y": {
           "scale": "y",
           "field": "label"
         },
         "height": {
           "value": 2
         },
         "fill": {
           "value": "#557"
         }
       }
     }
   },
   {
     "type": "rect",
     "from": {
       "data": "people"
     },
     "encode": {
       "enter": {
         "x": {
           "scale": "x",
           "field": "enter"
         },
         "x2": {
           "scale": "x",
           "field": "leave"
         },
         "y": {
           "scale": "y",
           "field": "label",
           "offset": -1
         },
         "height": {
           "value": 4
         },
         "fill": {
           "value": "#e44"
         }
       }
     }
   }
 ]

}</graph>

More maps examples

This transcludes the page Extension:Graph/Demo/Map. The ‎<graph> tag's JSON data on that page specifies that its countries data comes from a separate URL, Extension:Graph/Demo/RawData:WorldMap-iso2-json, that contains map data in JSON format. One of the elements in the ‎<graph> tag's JSON data specifies a highlight color for each country, in the format "country-code":"highlight-color":

{"BR":"pink","US":"blue","CN":"red","DZ":"green","AU":"purple"}

Vega usually works with data in the format [{"id":"country-code", "v":"highlight-color"}, ...], so I created a helper Lua function to convert the data:

{{#invoke:Graph:Utils|expandDict|{"BR":"pink","US":"blue","CN":"red","DZ":"green","AU":"purple"} }}

The Lua function's output is data in Vega's format:

[{"id":"US","v":"blue"},{"id":"AU","v":"purple"},{"id":"CN","v":"red"},{"id":"BR","v":"pink"},{"id":"DZ","v":"green"}]

<graph>{

   "version": 2,
   "width": 1,
   "height": 1,
   "data": [
       {
           "name": "highlights",
           "values": [{"id":"US","v":"blue"},{"id":"AU","v":"purple"},{"id":"CN","v":"red"},{"id":"BR","v":"pink"},{"id":"DZ","v":"green"}] 
       },
       {
           "name": "countries",
           "url": "wikiraw:///Extension:Graph/Demo/RawData:WorldMap-iso2-json",
           "format": {"type": "topojson", "feature": "countries"},
           "transform": [
               {
                   "type": "geopath",
                   "value": "data",
                   "scale": 90,
                   "translate":[0,0],
                   "projection": "equirectangular"
               },
               {
                   "type": "lookup",
                   "keys": [ "id" ],
                   "on": "highlights",
                   "onKey": "id",
                   "as": [ "zipped" ],
                   "default": {
                       "v": "#C0C0C0"
                   }
               }
           ]
       }
   ],
   "marks": [
       {
           "type": "path",
           "from": {
               "data": "countries"
           },
           "properties": {
               "enter": {
                   "path": {
                       "field": "layout_path"
                   }
               },
               "update": {
                   "fill": {
                       "field": "zipped.v"
                   }
               },
               "hover": {
                   "fill": {
                       "value": "#989898"
                   }
               }
           }
       }
   ]

}</graph>

Here is a more complex data processing example: MapTemplate is expanded with the data from Lua which takes it from the 2010 population distribution in the world (data based on UN data). To generate this graph, I use Lua module Graph:Utils's function parseCsv to extract the year 2010 column from the Extension:Graph/Demo/RawData:PopulationByCountryHistoric-csv page (in csv format), and pass that data as the first unnamed parameter to the MapTemplate graph. Additional optional parameter specifies that it should be scaled to 80%.

{{Extension:Graph/Demo/MapTemplate|{{#invoke:Graph:Utils|parseCsv|Extension:Graph/Demo/RawData:PopulationByCountryHistoric-csv|2010}}|scale=180}}

<graph> {

   "version": 2,
   "width": 1,
   "height": 1,
   "data": [
       {
           "name": "highlights",
           "url": "wikiraw:///Extension:Graph/Demo/RawData:PopulationByCountryHistoric-csv",
           "format": {"type": "csv"},
           "transform": [
               {
                   "type": "formula",
                   "field": "v",
                   "expr": "parseInt(datum['2010'])"
               }
           ]
       },
       {
           "name": "countries",
           "url": "wikiraw:///Extension:Graph/Demo/RawData:WorldMap-iso2-json",
           "format": {"type": "topojson", "feature": "countries"},
           "transform": [
               {
                   "type": "geopath",
                   "value": "data",
                   "scale": 180,
                   "translate":[0,0],
                   "projection": "equirectangular"
               },
               {
                   "type": "lookup",
                   "keys": ["id"],
                   "on": "highlights",
                   "onKey": "id",
                   "as": ["zipped"],
                   "default": { "v": 0 }
               }
           ]
       }
   ],
   "scales": [
       {
           "name": "color",
           "type": "sqrt",
           "domain": {"data": "highlights", "field": "v"},
           "zero": true,
           "range": ["#ffff65","#cb0000"]
       }
   ],
   "legends": [
       {
           "fill": "color",
           "offset":-300,
           "title": "Legend",
           "properties": {
               "gradient": {
                   "stroke": {"value": "transparent"}
               },
               "title": {
                   "fontSize": {"value": 14}
              },
           }
       }
   ],
   "marks": [
       {
           "type": "path",
           "from": {
               "data": "countries"
           },
           "properties": {
               "enter": {
                   "path": {
                       "field": "layout_path"
                   }
               },
               "update": { "fill": {"scale":"color", "field":"zipped.v"} },
               "hover": {
                   "fill": {
                       "value": "#989898"
                   }
               }
           }
       }
   ]

} </graph>

Note how the legend it wrongly positioned. That won't happen at lower scales.

Passing MediaWiki template parameters

If you're using a wiki page as a template, you can pass parameters to it, like any other MediaWiki template.

As an example, the graph specification in TemplateSample does not hardcode a fill color for marks.properties.update.fill.value; instead it sets the fill color to {{{1|#ccc}}}. So if you visit that page or transclude it with no parameter, the graph fills with color #ccc; but if you transclude that page you can specify the fill color as the first template parameter.

{{Extension:Graph/Demo/TemplateSample}}
{{Extension:Graph/Demo/TemplateSample | blue}}
{{Extension:Graph/Demo/TemplateSample | #f00dee}}

<graph>{

 "version": 2,
 "width": 100,
 "height": 100,
 "data": [
   {
     "name": "table",
     "values": [12,23,47,6,52,19],
     "transform": [{"type": "pie","field": "data"}]
   }
 ],
 "scales": [
   {
     "name": "r",
     "type": "sqrt",
     "domain": {"data": "table","field": "data"},
     "range": [20,100]
   }
 ],
 "marks": [
   {
     "type": "arc",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "startAngle": {"field": "layout_start"},
         "endAngle": {"field": "layout_end"},
         "innerRadius": {"value": 20},
         "outerRadius": {"scale": "r","field": "data"},
         "stroke": {"value": "#fff"}
       },
       "update": {"fill": {"value": "#ccc"} },
       "hover": {"fill": {"value": "pink"} }
     }
   },
   {
     "type": "text",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "radius": {"scale": "r","field": "data","offset": 8},
         "theta": {"field": "layout_mid"},
         "fill": {"value": "#000"},
         "align": {"value": "center"},
         "baseline": {"value": "middle"},
         "text": {"field": "data"}
       }
     }
   }
 ]

}</graph> <graph>{

 "version": 2,
 "width": 100,
 "height": 100,
 "data": [
   {
     "name": "table",
     "values": [12,23,47,6,52,19],
     "transform": [{"type": "pie","field": "data"}]
   }
 ],
 "scales": [
   {
     "name": "r",
     "type": "sqrt",
     "domain": {"data": "table","field": "data"},
     "range": [20,100]
   }
 ],
 "marks": [
   {
     "type": "arc",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "startAngle": {"field": "layout_start"},
         "endAngle": {"field": "layout_end"},
         "innerRadius": {"value": 20},
         "outerRadius": {"scale": "r","field": "data"},
         "stroke": {"value": "#fff"}
       },
       "update": {"fill": {"value": "blue"} },
       "hover": {"fill": {"value": "pink"} }
     }
   },
   {
     "type": "text",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "radius": {"scale": "r","field": "data","offset": 8},
         "theta": {"field": "layout_mid"},
         "fill": {"value": "#000"},
         "align": {"value": "center"},
         "baseline": {"value": "middle"},
         "text": {"field": "data"}
       }
     }
   }
 ]

}</graph> <graph>{

 "version": 2,
 "width": 100,
 "height": 100,
 "data": [
   {
     "name": "table",
     "values": [12,23,47,6,52,19],
     "transform": [{"type": "pie","field": "data"}]
   }
 ],
 "scales": [
   {
     "name": "r",
     "type": "sqrt",
     "domain": {"data": "table","field": "data"},
     "range": [20,100]
   }
 ],
 "marks": [
   {
     "type": "arc",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "startAngle": {"field": "layout_start"},
         "endAngle": {"field": "layout_end"},
         "innerRadius": {"value": 20},
         "outerRadius": {"scale": "r","field": "data"},
         "stroke": {"value": "#fff"}
       },
       "update": {"fill": {"value": "#f00dee"} },
       "hover": {"fill": {"value": "pink"} }
     }
   },
   {
     "type": "text",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"field": {"group": "width"},"mult": 0.5},
         "y": {"field": {"group": "height"},"mult": 0.5},
         "radius": {"scale": "r","field": "data","offset": 8},
         "theta": {"field": "layout_mid"},
         "fill": {"value": "#000"},
         "align": {"value": "center"},
         "baseline": {"value": "middle"},
         "text": {"field": "data"}
       }
     }
   }
 ]

}</graph>

Using a template for repeated graphs

This is very useful if you have multiple graphs of the same form: you can put the verbose graph JSON and additional repetive wikitext in a template and only pass the parameters to it that vary, such as title and values. See a sample of this approach.

Overlaying two types of data

Falkensee graph sample, see code.

Copied from vega demo, which was modeled on this graph. <graph>{ "version": 2, "width": 500, "height": 250, "padding": "auto", "data": [ { "name": "table", "values": [ {"year": 1875,"population": 1309}, {"year": 1890,"population": 1558}, {"year": 1910,"population": 4512}, {"year": 1925,"population": 8180}, {"year": 1933,"population": 15915}, {"year": 1939,"population": 24824}, {"year": 1946,"population": 28275}, {"year": 1950,"population": 29189}, {"year": 1964,"population": 29881}, {"year": 1971,"population": 26007}, {"year": 1981,"population": 24029}, {"year": 1985,"population": 23340}, {"year": 1989,"population": 22307}, {"year": 1990,"population": 22087}, {"year": 1991,"population": 22139}, {"year": 1992,"population": 22105}, {"year": 1993,"population": 22242}, {"year": 1994,"population": 22801}, {"year": 1995,"population": 24273}, {"year": 1996,"population": 25640}, {"year": 1997,"population": 27393}, {"year": 1998,"population": 29505}, {"year": 1999,"population": 32124}, {"year": 2000,"population": 33791}, {"year": 2001,"population": 35297}, {"year": 2002,"population": 36179}, {"year": 2003,"population": 36829}, {"year": 2004,"population": 37493}, {"year": 2005,"population": 38376}, {"year": 2006,"population": 39008}, {"year": 2007,"population": 39366}, {"year": 2008,"population": 39821}, {"year": 2009,"population": 40179}, {"year": 2010,"population": 40511}, {"year": 2011,"population": 40465}, {"year": 2012,"population": 40905}, {"year": 2013,"population": 41258}, {"year": 2014,"population": 41777} ] }, { "name": "annotation", "values": [ {"start": 1933,"end": 1945,"text": "Nazi rule"}, {"start": 1948,"end": 1989,"text": "GDR (East Germany)"} ] } ], "scales": [ { "name": "x", "type": "linear", "range": "width", "zero": false, "domain": {"data": "table","field": "year"} }, { "name": "y", "type": "linear", "range": "height", "nice": true, "domain": {"data": "table","field": "population"} }, { "name": "color", "type": "ordinal", "domain": {"data": "annotation","field": "text"}, "range": ["black","red"] } ], "axes": [ { "type": "x", "scale": "x", "format": "d", "title": "Year", "ticks": 15 }, { "type": "y", "scale": "y", "title": "Population", "grid": true, "layer": "back" } ], "marks": [ { "type": "rect", "from": {"data": "annotation"}, "properties": { "enter": { "x": {"scale": "x","field": "start"}, "y": {"value": 0}, "x2": {"scale": "x","field": "end"}, "y2": {"signal": "height"}, "fill": {"scale": "color","field": "text"}, "opacity": {"value": 0.2} } } }, { "type": "line", "from": {"data": "table"}, "properties": { "enter": { "interpolate": {"value": "monotone"}, "x": {"scale": "x","field": "year"}, "y": {"scale": "y","field": "population"}, "stroke": {"value": "steelblue"}, "strokeWidth": {"value": 3} } } }, { "type": "symbol", "from": {"data": "table"}, "properties": { "enter": { "x": {"scale": "x","field": "year"}, "y": {"scale": "y","field": "population"}, "stroke": {"value": "steelblue"}, "fill": {"value": "white"}, "size": {"value": 30} } } }, { "type": "text", "from": { "data": "table", "transform": [ { "type": "aggregate", "summarize": {"year": ["min","max"]} } ] }, "properties": { "enter": { "x": {"signal": "width","mult": 0.5}, "y": {"value": -10}, "text": { "template": "Population of Falkensee from \u007b{datum.min_year}\u007d to \u007b{datum.max_year}\u007d" }, "fill": {"value": "black"}, "fontSize": {"value": 16}, "align": {"value": "center"}, "fontWeight": {"value": "bold"} } } } ], "legends": [ { "fill": "color", "title": "Period", "properties": { "symbols": { "strokeWidth": {"value": 0}, "shape": {"value": "square"}, "opacity": {"value": 0.3} }, "legend": { "x": {"value": 10}, "y": {"value": 5}, "fill": {"value": "white"} } } } ] }</graph>

Horizontal bar graph

Extension:Graph/Demo/HorizontalBarGraphSample

<graph>{

 "version": 2, "width": 400, "height": 400,
 "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
 "data": [
   {
     "name": "table",
     "values": [
       {"t": "a", "v": 28}, {"t": "b", "v": 55},
       {"t": "c", "v": 43}, {"t": "d", "v": 91},
       {"t": "e", "v": 81}, {"t": "f", "v": 53},
       {"t": "g", "v": 19}, {"t": "h", "v": 87},
       {"t": "i", "v": 52}, {"t": "j", "v": 48},
       {"t": "k", "v": 24}, {"t": "l", "v": 49},
       {"t": "m", "v": 87}, {"t": "n", "v": 66},
       {"t": "o", "v": 17}, {"t": "p", "v": 27},
       {"t": "q", "v": 68}, {"t": "r", "v": 16},
       {"t": "s", "v": 49}, {"t": "t", "v": 15}
     ]
   }
 ],
 "scales": [
   {
     "name": "x",
     "range": "width",
     "domain": {"data": "table", "field": "v"}
   },
   {
     "name": "y",
     "range": "height",
     "type": "ordinal",
     "domain": {"data": "table", "field": "t"}
   }
 ],
 "axes": [
   {"type": "x", "scale": "x"},
   {"type": "y", "scale": "y"}
 ],
 "marks": [
   {
     "type": "rect",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "y": {"scale": "y", "field": "t"},
         "height": {"scale": "y", "band": true, "offset": -1},
         "x": {"scale": "x", "value": 0},
         "x2": {"scale": "x", "field": "v"}
       },
       "update": {
         "fill": {"value": "steelblue"}
       },
       "hover": {
         "fill": {"value": "red"}
       }
     }
   }
 ]

}</graph>

Embedded directly with ‎<graph>

This example is a ‎<graph> tag containing the graph JSON inside the current page.

<graph> {

 "version": 2, "width": 400, "height": 200,
 "padding": {"top": 10, "left": 30, "bottom": 30, "right": 10},
 "data": [
   {
     "name": "table",
     "values": [
       {"x": 1,  "y": 28}, {"x": 2,  "y": 55},
       {"x": 3,  "y": 43}, {"x": 4,  "y": 91},
       {"x": 5,  "y": 81}, {"x": 6,  "y": 53},
       {"x": 7,  "y": 19}, {"x": 8,  "y": 87},
       {"x": 9,  "y": 52}, {"x": 10, "y": 48},
       {"x": 11, "y": 24}, {"x": 12, "y": 49},
       {"x": 13, "y": 87}, {"x": 14, "y": 66},
       {"x": 15, "y": 17}, {"x": 16, "y": 27},
       {"x": 17, "y": 68}, {"x": 18, "y": 16},
       {"x": 19, "y": 49}, {"x": 20, "y": 15}
     ]
   }
 ],
 "scales": [
   {
     "name": "x",
     "type": "ordinal",
     "range": "width",
     "domain": {"data": "table", "field": "x"}
   },
   {
     "name": "y",
     "range": "height",
     "nice": true,
     "domain": {"data": "table", "field": "y"}
   }
 ],
 "axes": [
   {"type": "x", "scale": "x"},
   {"type": "y", "scale": "y"}
 ],
 "marks": [
   {
     "type": "rect",
     "from": {"data": "table"},
     "properties": {
       "enter": {
         "x": {"scale": "x", "field": "x"},
         "width": {"scale": "x", "band": true, "offset": -1},
         "y": {"scale": "y", "field": "y"},
         "y2": {"scale": "y", "value": 0}
       },
       "update": {
         "fill": {"value": "steelblue"}
       },
       "hover": {
         "fill": {"value": "red"}
       }
     }
   }
 ]

}</graph>

Editing graph data

Editing JSON by hand is fiddly and prone to error, so you should use a JSON checker such as JSONLint or a JSON editor such as the Vega Live Editor to edit JSON before you copy and paste it into the wiki page. If the ‎<graph> tag's data is directly embedded in the page such as the example above, then if you use VisualEditor to edit the page you can directly edit graph data.