我有这种形式的数据(经过简化,但假设 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 值
- 将每个 Mining-Admin 列分别除以 CPI,然后乘以 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 中的原始数据丢失。
我不确定是我在使用裸对象(同时在其中迭代,哎呀!)还是上面的代码实际上是在更改原始数据对象(以及该系列的所有 4 个对象)中的值我创建之后只是对它的引用)。
不管怎样,我都解决不了!我尝试了几种不同的语法形式,但无法解决。帮助实现这一目标将不胜感激。
最佳答案
如果您确实使用此代码来“复制”您的数组:
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;
});
});
祝你好运!
关于javascript - 从 d3 中的系列创建系列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37006725/