Extension:Graph/Demo
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/2024112519/2024122519", "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/2024112519/2024122519", "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/2024112519/2024122519", "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/2024112519/2024122519", "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/2024112519/2024122519", "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/2024112519/2024122519", "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.