This is a d3 chart representing multiple time series paths, where missing values are breaking the paths.
You can view a rendered version of this gist at bl.ocks.org.
This is a d3 chart representing multiple time series paths, where missing values are breaking the paths.
You can view a rendered version of this gist at bl.ocks.org.
function mlineChart() { | |
var outerWidth = 960; | |
var outerHeight = 500; | |
var y = d3.scale.log(); | |
var yAxisLabel = ""; | |
function mlineChartInner(selection) { | |
selection.each(function(data){ | |
// define margins | |
var margin = {top: 20, right: 80, bottom: 30, left: 150}; | |
// graphics size without axis | |
var width = outerWidth - margin.left - margin.right; | |
var height = outerHeight - margin.top - margin.bottom; | |
var svg = d3.select(this).append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
var x = d3.time.scale() | |
.range([0, width]); | |
y = y.range([height, 0]); | |
var color = d3.scale.category10(); | |
var xAxis = d3.svg.axis() | |
.scale(x) | |
.orient("bottom"); | |
var yAxis = d3.svg.axis() | |
.scale(y) | |
.orient("left") | |
.ticks(5); | |
var parseDate = d3.time.format("%Y-%m-%d").parse; | |
var line = d3.svg.line() | |
.defined(function(d) { return !isNaN(d.gdp); }) | |
.interpolate("basis") | |
.x(function(d) { return x(d.idx); }) | |
.y(function(d) { return y(d.gdp); }); | |
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "idx"; })); | |
data.forEach(function(d) { | |
d.idx = parseDate(d.idx); | |
}); | |
var tseries = color.domain().map(function(name) { | |
countryData = data.map(function(d) { | |
return {idx: d.idx, gdp: +d[name]}; | |
}) | |
return {name: name, | |
values: countryData | |
}; | |
}); | |
x.domain(d3.extent(data, function(d) { return d.idx; })); | |
y.domain([ | |
d3.min(tseries, function(c) { return d3.min(c.values, function(v) { return v.gdp; }); }), | |
d3.max(tseries, function(c) { return d3.max(c.values, function(v) { return v.gdp; }); }) | |
]); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis) | |
.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.text(yAxisLabel); | |
var gdp = svg.selectAll(".gdp") | |
.data(tseries) | |
.enter().append("g") | |
.attr("class", "gdp"); | |
gdp.append("path") | |
.attr("class", "line") | |
.attr("d", function(d) { return line(d.values); }) | |
.style("stroke", function(d) { return color(d.name); }); | |
}) | |
} | |
mlineChartInner.width = function(value) { | |
if (!arguments.length) return outerWidth; | |
outerWidth = value; | |
return mlineChartInner; | |
}; | |
mlineChartInner.height = function(value) { | |
if (!arguments.length) return outerHeight; | |
outerHeight = value; | |
return mlineChartInner; | |
}; | |
mlineChartInner.y = function(value) { | |
if (!arguments.length) return y; | |
y = value; | |
return mlineChartInner; | |
}; | |
mlineChartInner.yAxisLabel = function(value) { | |
if (!arguments.length) return yAxisLabel; | |
yAxisLabel = value; | |
return mlineChartInner; | |
}; | |
return mlineChartInner; | |
} |
idx | BR | DE | US | |
---|---|---|---|---|
1962-12-31 | 229.30286512437993 | NA | 3279.847682222698 | |
1963-12-31 | 249.81937267525998 | NA | 3409.2535616487735 | |
1964-12-31 | 270.5971235206717 | NA | 3609.9894994132137 | |
1965-12-31 | 271.1335322289991 | NA | 3879.634758987967 | |
1966-12-31 | 271.9748253456187 | NA | 4199.058901057487 | |
1967-12-31 | 310.83529938661604 | NA | 4379.433646211674 | |
1968-12-31 | 370.04114717388 | NA | 4750.4360922898695 | |
1969-12-31 | 412.00850429246634 | NA | 5080.319198124847 | |
1970-12-31 | 441.3565057674224 | NA | 5280.974624363576 | |
1971-12-31 | 499.9595643842608 | NA | 5690.311399081065 | |
1972-12-31 | 589.2271929448656 | 3599.9227119065013 | 6329.125786229267 | |
1973-12-31 | 748.8759295108167 | 4679.567597052115 | 7340.426065533109 | |
1974-12-31 | 970.3270684879265 | 5799.341880719011 | 8037.949676827828 | |
1975-12-31 | 1169.5536454723958 | 6730.185541715934 | 8600.61146075292 | |
1976-12-31 | 1348.8458554176366 | 7140.066028103141 | 9079.04617203539 | |
1977-12-31 | 1480.1905207591387 | 7680.292400333419 | 9698.53046420326 | |
1978-12-31 | 1659.7854890643039 | 8879.836986345166 | 10890.159271647331 | |
1979-12-31 | 1949.7020741086164 | 11069.431092647033 | 12438.123052145473 | |
1980-12-31 | 2180.597449054458 | 13021.026407704185 | 13619.920660882619 | |
1981-12-31 | 2079.2795805880287 | 12559.540641721003 | 14559.383186084424 | |
1982-12-31 | 2001.4421874323805 | 11138.550463383071 | 14269.772235170483 | |
1983-12-31 | 1709.856363380952 | 10029.733936048005 | 14818.664041979862 | |
1984-12-31 | 1620.7081454525671 | 9889.928878797436 | 16390.8943166959 | |
1985-12-31 | 1569.3311142468945 | 9850.015022771056 | 17710.337169468505 | |
1986-12-31 | 1790.6719328592344 | 11249.34566555451 | 19490.933269800964 | |
1987-12-31 | 2038.8167549728864 | 14250.16356675534 | 21660.723087427028 | |
1988-12-31 | 2250.683489101661 | 18640.104070736023 | 23579.149889706885 | |
1989-12-31 | 2749.303390614975 | 19778.999509391182 | 24129.881087096743 | |
1990-12-31 | 2699.480477119376 | 21330.140841059732 | 24528.63498868993 | |
1991-12-31 | 2869.8214516711114 | 22910.973069442614 | 24720.624693604812 | |
1992-12-31 | 2778.438816523024 | 25848.499966560907 | 26220.950943270618 | |
1993-12-31 | 2741.0072737850155 | 25980.081030464215 | 27081.057182442157 | |
1994-12-31 | 3039.02985807059 | 27519.02537250676 | 28280.415146738338 | |
1995-12-31 | 3731.316086414115 | 29549.94418495954 | 29490.817825154543 | |
1996-12-31 | 4460.847389920484 | 30880.788261334674 | 30601.65197112317 | |
1997-12-31 | 5049.685084457657 | 30161.190700728657 | 31429.771448183077 | |
1998-12-31 | 4870.6934805001565 | 27948.92519939022 | 31941.13411108418 | |
1999-12-31 | 4129.39658226453 | 26839.036449653515 | 33669.769780494426 | |
2000-12-31 | 3858.475965422518 | 26170.00710763633 | 35739.586487263776 | |
2001-12-31 | 3290.0748813152604 | 24749.962278555795 | 36448.153495558916 | |
2002-12-31 | 3051.278096249819 | 23679.626748199647 | 37218.8427269532 | |
2003-12-31 | 2949.1091800149575 | 26210.0781319859 | 39900.91430544001 | |
2004-12-31 | 3308.7609276426247 | 31709.80579699382 | 43649.82282887204 | |
2005-12-31 | 3958.5005089530937 | 35881.15358401915 | 46220.00791960031 | |
2006-12-31 | 4799.546579029736 | 38379.766904028154 | 47339.40891836694 | |
2007-12-31 | 6097.848850073046 | 40729.41756576593 | 48690.56814902777 | |
2008-12-31 | 7478.301064611335 | 43909.92820788725 | 49681.16808555389 | |
2009-12-31 | 8139.116785302867 | 43810.411824587085 | 48300.71881589496 | |
2010-12-31 | 9520.884317818694 | 44780.269029070514 | 49111.11332148076 | |
2011-12-31 | 10698.096717138249 | 46409.62596787164 | 50350.82969561104 | |
2012-12-31 | 11638.478402286351 | 46701.88913672164 | 51921.71495220139 | |
2013-12-31 | 11689.673103149926 | 47269.584174007585 | 53470.78316792905 |
using TimeData | |
using WorldBankDataTd | |
## download data | |
dataRaw = WorldBankDataTd.wdi(["NY.GNP.PCAP.CD"], | |
["BR", "US", "DE"]) | |
## convert to wide format | |
df = convert(DataFrame, dataRaw) | |
dfWide = unstack(df, :idx, :iso2c, symbol("NY.GNP.PCAP.CD")) | |
data = Timenum(dfWide[:, 2:end], dfWide[:, 1]) | |
## randomize entries, as I am not allowed to redistribute World Bank | |
## data | |
function randomizeSorted(da::DataArray) | |
## preserving time rend | |
## get mean change | |
mnChg = mean(dropna(diff(da))) | |
## add half of mean change | |
nObs = size(da, 1) | |
return da + randn(nObs).*(sqrt(mnChg/2)) | |
end | |
function randomize(da::DataArray) | |
## get variation | |
dataVar = var(dropna(diff(da))) | |
## add quarter of variance | |
nObs = size(da, 1) | |
return da + randn(nObs).*(sqrt(dataVar)/2) | |
end | |
## apply randomization | |
nObs = size(data, 1) | |
randomizedData = map(x -> x .+ randn(nObs), eachcol(data)) | |
## write data to disk | |
writeTimedata("dummyData.csv", randomizedData) |
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
body { | |
font: 16px sans-serif; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.x.axis path { | |
<!-- display: none; --> | |
} | |
.line { | |
fill: none; | |
stroke: steelblue; | |
stroke-width: 1.5px; | |
} | |
.grid .tick { | |
stroke: lightgrey; | |
stroke-opacity: 0.7; | |
shape-rendering: crispEdges; | |
} | |
.grid path { | |
stroke-width: 0; | |
} | |
</style> | |
<body> | |
<!-- <script src="../d3/d3.min.js" charset="utf-8"> --> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"> | |
</script> | |
<script src="assembly_code.js"></script> | |
<script> | |
var actualChart = mlineChart() | |
.width(900) | |
.y(d3.scale.linear()) | |
.yAxisLabel("gdp in $"); | |
d3.csv("dummyData.csv", function(inputData) { | |
d3.select("body") | |
.datum(inputData) | |
.call(actualChart) | |
}); | |
</script> | |
</body> | |
</html> |