2017-03-07 47 views
1

我试图让基于这个例子由迈克·博斯托克与D3了多系列折线图:这个D3多系列线图中的行功能是做什么的?

https://bl.ocks.org/mbostock/3884955

我有一个很难试图了解加载data.tsv文件后,会发生什么,特别是“类型”功能。它似乎解析数据并将温度字符串转换为数字。还有什么它做,为什么有必要?:

function type(d, _, columns) { 
    d.date = parseTime(d.date); 
    for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c]; 
    return d; 
} 

下面是完整的代码:

var svg = d3.select("svg"), 
    margin = {top: 20, right: 80, bottom: 30, left: 50}, 
    width = svg.attr("width") - margin.left - margin.right, 
    height = svg.attr("height") - margin.top - margin.bottom, 
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var parseTime = d3.timeParse("%Y%m%d"); 

var x = d3.scaleTime().range([0, width]), 
    y = d3.scaleLinear().range([height, 0]), 
    z = d3.scaleOrdinal(d3.schemeCategory10); 

var line = d3.line() 
    .curve(d3.curveBasis) 
    .x(function(d) { return x(d.date); }) 
    .y(function(d) { return y(d.temperature); }); 

d3.tsv("data.tsv", type, function(error, data) { 
    if (error) throw error; 

    var cities = data.columns.slice(1).map(function(id) { 
    return { 
     id: id, 
     values: data.map(function(d) { 
     return {date: d.date, temperature: d[id]}; 
     }) 
    }; 
    }); 

    x.domain(d3.extent(data, function(d) { return d.date; })); 

    y.domain([ 
    d3.min(cities, function(c) { return d3.min(c.values, function(d) { return d.temperature; }); }), 
    d3.max(cities, function(c) { return d3.max(c.values, function(d) { return d.temperature; }); }) 
    ]); 

    z.domain(cities.map(function(c) { return c.id; })); 

    g.append("g") 
     .attr("class", "axis axis--x") 
     .attr("transform", "translate(0," + height + ")") 
     .call(d3.axisBottom(x)); 

    g.append("g") 
     .attr("class", "axis axis--y") 
     .call(d3.axisLeft(y)) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", "0.71em") 
     .attr("fill", "#000") 
     .text("Temperature, ºF"); 

    var city = g.selectAll(".city") 
    .data(cities) 
    .enter().append("g") 
     .attr("class", "city"); 

    city.append("path") 
     .attr("class", "line") 
     .attr("d", function(d) { return line(d.values); }) 
     .style("stroke", function(d) { return z(d.id); }); 

    city.append("text") 
     .datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; }) 
     .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; }) 
     .attr("x", 3) 
     .attr("dy", "0.35em") 
     .style("font", "10px sans-serif") 
     .text(function(d) { return d.id; }); 
}); 

function type(d, _, columns) { 
    d.date = parseTime(d.date); 
    for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c]; 
    return d; 
} 

回答

3

该行函数(这里命名type)其实就是做眼前这个:

function type(d){ 
    d.date = parseTime(d.date); 
    d["New Your"] = +d["New Your"]; 
    d["San Francisco"] = +d["San Francisco"]; 
    d["Austin"] = +d["Austin"]; 
    return d; 
} 

因此,它基本上解析date属性,并将所有其他属性强制为数字,正如您正确猜测的那样。

它还能做什么?

没什么,只是。

为什么有必要?

即使您的CSV或TSV值是数字,d3.csvd3.tsv填充物与,而不是数字。他们需要转换为数字。

关于date很明显他们需要解析。

说明

d3.csvd3.tsv接受连续转换功能。该函数有三个定义的参数:

如果指定了行转换函数,则为每行调用指定的函数,传递一个表示当前行(d)的对象,索引(i)从零开始第一个非标题行和列名称数组。

如此说来,在type功能:

  • d是表示每行
  • _是其该对象的索引和
  • columns是标题行整个对象。

在你的情况,这是columns

["date", "New York", "San Francisco", "Austin"] 

现在,让我们来分析for...循环。

可变i开始于1(避免date)和结束于3.对于每个循环,它得到一个属性...

d[c = columns[i]] 

...并且强制其值(这是一个字符串)多项:

columns[i]] = +d[c]; 

因此,例如,在第一循环中,当i = 1,这是发生了什么:

d[c = "New York"] = +d[c]; 

所有其他属性都会发生同样的情况。然后,对于下一行(对象),for..再次循环,依此类推,直到数据数组结束。

这里是一个只有三排演示:

var parseTime = d3.timeParse("%Y%m%d"); 
 
var data = d3.csvParse(d3.select("#csv").text(), type); 
 

 
function type(d, _, columns) { 
 
    d.date = parseTime(d.date); 
 
    for (var i = 1, n = columns.length, c; i < n; ++i) { 
 
    d[c = columns[i]] = +d[c]; 
 
    console.log("row is " + _ +",columns[i] is " + columns[i] + ", +d[c] is " + (+d[c])) 
 
    } 
 
    return d; 
 
}
pre { 
 
    display: none; 
 
}
<script src="//d3js.org/d3.v4.min.js"></script> 
 
<pre id="csv">date,New York,San Francisco,Austin 
 
20111001,63.4,62.7,72.2 
 
20111002,58.0,59.9,67.7</pre>

PS:我建议你修改你的问题的标题。标题是问题中最重要的部分,96.38%的用户(来源:FakeData Inc.)只读取标题。现在,你的问题与你真正的问题不符。因此,它可能是“这个代码中的行函数做了什么?”或类似的东西。