2014-03-14 118 views
0

我正在嘗試將多行圖形合併到一個關於城市和溫度的Bostock示例中。D3多系列折線圖從tsv文件中獲取我的國家數據

例子就在這裏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文件中的建議是爲了繪製GDP,人口等因素對不同的SVG圖形;爲了方便起見,我把它放在一個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

你可以用硬編碼數據在[jsFiddle](http://jsfiddle.net)上對此進行演示嗎? –

+0

我可悲的不能,因爲我專注於嘗試讀取這些數據。令人困惑的是我需要使用jsFiddle進行操作? – kthieu

+0

所以基本上你的問題只是格式化數據,就像你在上面引用的Bostock例子那樣?在他的例子中,每一行都是單列,而在每個國家都有多行記錄。對? –

回答

1

要創建與D3多線圖方面目前我在,你需要

  1. 創建一個頂級的數據陣列,每個數據系列(即圖表上的每一行)都有一個條目;和
  2. 對於每個數據系列,以標準格式創建一個包含該系列數據的(x,y)點數組。

當您的數據爲表格格式時,如果您可以硬編碼表示要用作數據序列的列的列名稱數組,那麼每個系列都位於單獨的列中。

var seriesNames = ["GDP", "Population", "GDP per Capita", "Exports", "Industry"]; 

如果你不希望在所有的系列名稱硬編碼,你將至少需要知道將用於x值和任何其他列的列的名稱不包括。然後,您可以從d3.keys(data[0])獲取所有列的名稱,並使用數組篩選器來擺脫「Year」和「Country Name」值。您鏈接到邁克·博斯托克例如這是否設置色階的域時,然後抓起從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) }; 
     }) 
    }; 
});