在d3

时间:2016-05-03 14:17:13

标签: javascript d3.js

我有这种形式的数据(简化,但假设Admin和Mining之间有20列):

Date,Series,Admin,Mining,CPI
1990,Ordinary Time Earnings,20,30,96
1991,Ordinary Time Earnings,22,33,100
1990,Total Earnings,25,38,96
1991,Total Earnings,29,43,100

我把它分成两个这样的系列:

d3.csv("avgearnings_v1_1.csv", function(error, data) {
  if (error) throw error;
  OrdinaryTimeEarnings = data
    .filter(function(d) {
        if(d.Series == 'Ordinary Time Earnings')
            return d;
    });
  TotalEarnings = data
    .filter(function(d) {
        if(d.Series == "Total Earnings")
            return d;
    });

并且可以在没有任何问题的情况下显示在图表上。我接下来要做的是创建另外两个系列:

OrdinaryTimeEarningsReal = OrdinaryTimeEarnings;
TotalEarningsReal = TotalEarnings;

然后重新计算这些新系列。基本上是:

  • 对于任何非日期/系列/ CPI
  • 的列
  • 取当年的CPI值
  • 按CPI单独划分每个Mining-Admin列并乘以100.
  • 所以:新值=([旧值] / [CPI])* 100

我的代码非常糟糕,但我可以使用这个来获取正确的值:

OrdinaryTimeEarningsReal
    .forEach(function (z,i) {
        var CPI = z["CPI"];
        d3.map(z, function(b) {return b;})
            .forEach(function (c) {
                if(c !== "Date" && c !== "Series" && c !== "CPI" ) 
                    OrdinaryTimeEarningsReal[i][c] = ((z[c])/(CPI))*100;       
            });
    });

但是,当我这样做时,它也会以某种方式更新原始的OrdinaryTimeEarnings系列,使它们彼此相等,而且OrdinaryTimeEarnings中的原始数据也会丢失。

我不确定我是否使用裸对象(在其中迭代,eek!)或上面的代码实际上是在更改原始数据中的值对象(以及我之后创建的所有4个系列都只是对它的引用)。

无论哪种方式,我都无法解决这个问题!我尝试了几种不同的语法形式,但无法解决问题。非常感谢帮助实现这一目标。

2 个答案:

答案 0 :(得分:2)

如果您确实使用此代码“复制”数组:

OrdinaryTimeEarningsReal = OrdinaryTimeEarnings;
TotalEarningsReal = TotalEarnings;

然后你提到它是正确的,当你说他们引用同一个对象时。在JavaScript中,数组是可变的,使用上面的代码,您只需创建2个新变量,并引用内存中的现有数组。

要深度克隆对象数组,请使用以下方法:

OrdinaryTimeEarningsReal = JSON.parse(JSON.stringify(OrdinaryTimeEarnings));
TotalEarningsReal = JSON.parse(JSON.stringify(TotalEarnings));

这将创建数组的副本并将它们分配给新变量,这样当您编辑它们时,初始数组将不受影响。

现在,关于你的代码,它有点太复杂了。如果我理解你想要实现什么,你可以按如下方式简化它:

OrdinaryTimeEarningsReal
.forEach(function (z,i) {
    for (var c in z) {
        if (z.hasOwnProperty(c) && c !== "Date" && c !== "Series" && c !== "CPI" ) 
            z[c] = z[c] / z.CPI * 100;       
    });
});
祝你好运!

答案 1 :(得分:1)

如果我理解正确:

data.forEach(function(d) { 
  for (var key in d) {
    if (key !== 'Date' && key !== 'Series' && key !== 'CPI') {
      d['new' + key] = (d[key] / d.CPI) * 100;
    }
  }
})
console.log(data)

我已将new添加到新属性中,因此新的admin值为newAdmin

实施小提琴:https://jsfiddle.net/thatOneGuy/9ywLytjf/