我正试图在Bostock关于城市和温度的例子中做多个线图。
示例就在这里http://bl.ocks.org/mbostock/3884955
现在,我有一个由世界数据库信息定制的tsv文件。格式如下
Country Name Year GDP Population GDP per Capita Exports Industry
Brazil 2004 663760341880.342 184010283 3607.1915713555 16.4250921582 30.1135838508
Brazil 2005 882185702547.247 186142403 4739.3054367481 15.1283508131 29.27296088
Brazil 2006 1088916819852.94 188134315 5787.9755740091 14.3684508393 28.7527649158
Brazil 2007 1366853244424.28 189996976 7194.0789437843 13.3643803148 27.8112224671
Brazil 2008 1653538618144.8 191765567 8622.7086750397 13.6631968034 27.901606309
Brazil 2009 1620165226993.77 193490922 8373.3397424907 10.9789949015 26.8288327492
Brazil 2010 2143035333258.24 195210154 10978.093553772 10.8715851234 28.0694513261
Brazil 2011 2476652189879.72 196935134 12575.9794079188 11.8891676714 27.5330208705
Brazil 2012 2252664120777.39 198656019 11339.5211084814 12.557350455 26.2886840461
我有不同年份的多个国家/地区输入。格式是建议来自另一个帖子问题的答案
D3 Getting values from keys using array of objects
此TSV文件用于在单独的svg图上绘制GDP,人口等图表;为方便起见,我把它放在一个tsv文件中。现在,我的下一步是从数据中提取国家/地区并将其绘制为线条。该示例将城市作为标题行中的键,由d3.keys调用解析。但是,我的国家有一个名为国名的密钥,如上所示。我如何解析我的数据,以便每个国家获得一行?
这就是我目前在编码方面的目标
//Define Margin Object with properties from the four sides Clockwise
var margin = {top: 20, right: 80, bottom: 30, left: 50};
var dataset;
//Width and Height as inner dimensions of chart area
var width = 960 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
//Define svg
var svg = d3.select("#chart").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.scale.linear()
.range([0, width]);
var y = d3.scale.linear()
.range([0, height]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) {return x(d.year);})
.y(function(d) {return y(d.GDP);});
d3.tsv("OlympicsData.tsv", function(error, data) {
x.domain(d3.extent(data, function(d) {return d["Year"];}));
y.domain(d3.extent(data, function(d) {return d["GDP"];}));
console.log(d3.min(data, function(d) {return d["Year"];}) + " " + d3.max(data, function(d) {return d["Year"];}));
svg.append("g")
.attr("class", "x axis")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
答案 0 :(得分:1)
要使用d3创建多线图,您需要
当您的数据采用表格格式时,每个系列都在单独的列中,如果您可以对表示要用作数据系列的列的列名称进行硬编码,这将变得更加容易。
var seriesNames = ["GDP", "Population", "GDP per Capita", "Exports", "Industry"];
如果您不想在所有系列名称中进行硬编码,则至少需要知道将用于x值的列的名称以及不包括的任何其他列。然后,您可以从d3.keys(data[0])
获取所有列的名称,并使用数组过滤器来删除“Year”和“Country Name”值。您链接到的Mike Bostock示例在设置色标的域时执行此操作,然后从color.domain()
抓取数组以供将来使用:
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
我发现这令人困惑,并且会首先在变量中保存名称数组,然后使用它来设置颜色标度的域:
var seriesNames = d3.keys(data[0]).filter(function(key) {
return key !== "date";
//you would have to change the name(s) to exclude
});
color.domain( seriesNames );
无论是硬编码还是动态创建,您都可以使用系列名称数组来创建数组:
var series = seriesNames.map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {x: d.year,
y: +d[name] };
})
};
});
数组map
函数创建一个新数组,其中每个条目都是将相应的条目从起始数组传递给映射函数的结果。此代码使用两个级别的映射:外部函数获取系列名称并返回数据对象,内部函数获取原始数据数组并仅提取与此系列相关的值,并使用标准化名称然后使用在你的其余代码中。
这应该让你开始,但是你的数据中有一个复杂功能不在你正在使用的例子中:你的数据系列都代表完全不同的数字类型,具有完全不同的比例。我不确定你是如何计划在同一个图表上绘制所有这些值的图表,但是一个选项是绘制从起始年份开始的百分比变化。您可以在数据映射函数中进行计算:
var series = seriesNames.map(function(name) {
var initialValue = +data[0][name];
return {
name: name,
values: data.map(function(d) {
return {year: d.year,
percentChange: (+d[name] / initialValue) };
})
};
});