I'm trying to do multiple lines graphs into one following Bostock's example on city and temperature.

Example is right here http://bl.ocks.org/mbostock/3884955

Now, I have a tsv file custom made from info from world databank. The format is as follows

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

Where I have multiple country inputs for different years. The format is at the suggestion of an answer from another post question here

D3 Getting values from keys using array of objects

This TSV file is meant to graph GDP, Population, etc on separate svg graphs; I put it into one tsv file for convenience. Now, my next step is to extract the countries from my data and graph them as lines. The example has cities as keys in the header line, parsed by d3.keys call. My countries, however, are in one key called Country Name, as shown above. How would I parse my data such that I get one line for each country?

Here is where I'm currently at in terms of coding

//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);
});
有帮助吗?

解决方案

To create a multi-line chart with d3, you need to

  1. Create a top-level data array, with one entry for each data series (i.e., for each line on the chart); and
  2. For each data series, create an array of (x,y) points containing that series' data in a standard format.

When your data is in a table format, with each series in separate column, this gets much easier if you can hard-code an array of column names representing the columns that you want to use as data series.

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

If you don't want to hard-code in all the series names, you will at least need to know the names of the column that will be used for the x values and any other columns not to include. Then you can get the names of all columns from d3.keys(data[0]), and use an array filter to get rid of the "Year" and "Country Name" values. The Mike Bostock example you linked to does this when setting the domain of the colour scale, and then grabs the array for future use from color.domain():

color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));

I find that confusing, and would save the array of names in a variable first, then use it to set the domain of the colour scale:

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 );

Whether you hard-code it or create it dynamically, you can then use your array of series names to create your array of arrays:

var series = seriesNames.map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {x: d.year, 
                y: +d[name] };
      })
    };
});

The array map function creates a new array where each entry is the result of passing the corresponding entry from the starting array to the mapping function. This code uses two levels of mapping: the outer function takes your series name and returns a data object, the inner function takes the original data array and extracts only the values that are relevant to this series, with a standardized name that you can then use in the rest of your code.

That should get you started, but there's one complication in your data that isn't in the example you're working from: your data series all represent completely different types of numbers, with completely different scales. I'm not sure how you were planning to handle that for graphing all these values on the same chart, but one option would be to graph percent change from the starting year. You could do that calculation in your data-mapping function:

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) };
      })
    };
});
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top