嵌套对象的解析错误?

时间:2013-03-10 11:34:13

标签: javascript d3.js

有人可以帮忙吗?我的数据按照从两个下拉列表中选择的值进行过滤 - 然后嵌套/汇总以获得这些相同值的每日平均值。我为下面的代码得到了“解析d错误的问题”。尽管filter和nest函数都返回了正确的数据 - 当我尝试将这些数据应用到折线图来更新它时会出现问题?

    d3.select("#parameterType").on("change", function() 
    {   
    d3.select("#dateTimeTaken").on("change", function()
    {   
    var selectedParameter = document.getElementById("parameterType").value;
    var selectedMonth = document.getElementById("dateTimeTaken").value;

    //filter data by selected parameter and month    
    var selectedData = data.filter(function(d) { 
      return d.parameterType == selectedParameter  &&
      +d.dateTimeTaken.getMonth() == (selectedMonth - 1);});

    console.log(selectedData);//returning correct data

    //get average reading for each day within selected month 
    var newdata = d3.nest()
        .key(function(d) {return d3.time.day(d.dateTimeTaken);})    
        .sortKeys(d3.ascending)
        .rollup(function(d) 
        {
            return {
            mean: d3.mean(selectedData, function(d) {return +d.reading;})};
        })
    .entries(selectedData);
    console.log(newdata);//returning correct data

    //UPDATE GRAPH

    //not returning correct max values?     
    x.domain(d3.extent(newdata, function(d) { return d.key; }));
    y.domain([0, d3.max(newdata, function(d) { return d.values; })]);

    svg.select("path.line")
        .attr( "d", line(newdata));

    svg.select(".x.axis")
        .transition()
        .duration(750)
        .ease("linear")
        .call(xAxis);

    svg.select(".y.axis")
        .transition()
        .duration(750)
        .ease("linear")
        .call(yAxis);

1 个答案:

答案 0 :(得分:2)

code that you posted中,导致上述问题的问题有两个。这两个问题似乎都源于对D3中数据如何嵌套和汇总的误解。

解释

var newdata = d3.nest()
    .key(function(d) {return d.dateTimeTaken;})    
    .sortKeys(d3.ascending)
    .entries(data);

这会转换以下类型的对象:

var data = [{
    parameterType: 'a',
    dateTimeTaken: '2013-01-01 12:00:00',
    reading: 100
}, {
    parameterType: 'a',
    dateTimeTaken: '2013-01-02 12:00:01',
    reading: 101
}];

为:

[
    {
        "key": "2013-01-01 12:00:00",
        "values": [
            {
                "parameterType": "a",
                "dateTimeTaken": "2013-01-01 12:00:00",
                "reading": 100
            }
        ]
    },
    {
        "key": "2013-01-02 12:00:01",
        "values": [
            {
                "parameterType": "a",
                "dateTimeTaken": "2013-01-02 12:00:01",
                "reading": 101
            }
        ]
    }
]

values字段是一个将原始数据条目累加在一起的数组。 rollup然后将数组作为参数values,从这些数据计算聚合度量(在您的情况下为mean),将其替换为数组中的数组键values

您的rollup功能:

//AVERAGE READING FOR EACH DAY WITHIN SELECTED MONTH FOR SELECTED PARAMETER
// ...

 .rollup(function(d) {
    return {mean:d3.mean(selectedData, function(d) {return +d.reading;})};})

完全忽略了这个论点。我认为它应该是:

 .rollup(function(d) {
    return {mean:d3.mean(d, function(d_) {return +d_.reading;})};})

现在生成的数组会:

[
    {
        "key": "2013-01-01 12:00:00",
        "values": {
            "mean": 100
        }
    },
    {
        "key": "2013-01-02 12:00:01",
        "values": {
            "mean": 101
        }
    }
]

请注意,values键中还有另一个包含mean的对象。您将y轴的范围计算为:

y.domain([0, d3.max(newdata, function(d) { return d.values; })]);

最大值不正确的原因是因为您要求d3计算objectsvalues的最大值。这种操作的结果是不明确的。相反,您应该要求最大值超过values.mean

y.domain([0, d3.max(newdata, function(d) { return d.values.mean; })]);

这可以产生正确的结果,如jsFiddle:http://jsfiddle.net/XLNeP/

所示

结论

这是关于如何使嵌套和汇总正常工作。现在解决其他一些问题。您的line变量具有以下访问者:

var line = d3.svg.line()
.x(function(d) { return x(d.dateTimeTaken); })
    .y(function(d) { return y(d.reading); });

这适用于你打电话的时间:

svg.append("path")
    .attr("class", "line")
    .attr("d", line(data)); 

但是,newdata的格式如上所示,其顶级keyvalues而非dateTimeTakenreading。因此,最好使用仅selectedData过滤的data并保留数据结构。但是,如果要绘制不同的行(例如,使用mean),则应定义具有不同访问者的新d3.svg.line()行生成器。