Javascript 数据整理:计算嵌套 json 中的百分比变化

Javascript data wrangling: Calculate percent change in a nested json

有一个 json 这种格式的文件...

data =[
  {
  key: "london",
  values: [
   {day: "2020-01-01", city: "london", value: 10},
   {day: "2020-01-02", city: "london", value: 20},
   {day: "2020-01-03", city: "london", value: 30},
   {day: "2020-01-04", city: "london", value: 30},
   {day: "2020-01-05", city: "london", value: 30},
   {day: "2020-01-06", city: "london", value: 30}
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", city: "berlin", value: 10},
   {day: "2020-01-02", city: "berlin", value: 15},
   {day: "2020-01-03", city: "berlin", value: 30},
   {day: "2020-01-04", city: "berlin", value: 30},
   {day: "2020-01-05", city: "berlin", value: 30},
   {day: "2020-01-06", city: "berlin", value: 45}
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", city: "rome", value: 10},
   {day: "2020-01-02", city: "rome", value: 12},
   {day: "2020-01-03", city: "rome", value: 6},
   {day: "2020-01-04", city: "rome", value: 9},
   {day: "2020-01-05", city: "rome", value: 27},
   {day: "2020-01-06", city: "rome", value: 36}
  ]
  }]

我想知道如何使用 javascript 计算系列中的每日百分比变化。我期待得到以下输出。如果可能,我想删除 city 以免重复信息。

data =[
  {
  key: "london",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-02", value: 20, perc: 1},
   {day: "2020-01-03", value: 30, perc: 1},
   {day: "2020-01-04", value: 30, perc: 0},
   {day: "2020-01-05", value: 30, perc: 0},
   {day: "2020-01-06", value: 30, perc: 0}
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-02", value: 15, perc: 0.5},
   {day: "2020-01-03", value: 30, perc: 1},
   {day: "2020-01-04", value: 30, perc: 0},
   {day: "2020-01-05", value: 30, perc: 0},
   {day: "2020-01-06", value: 45, perc: 0.5}
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-02", value: 12, perc: 0.2},
   {day: "2020-01-03", value: 6, perc: -0.5},
   {day: "2020-01-04", value: 9, perc: 0.5},
   {day: "2020-01-05", value: 27, perc: 2},
   {day: "2020-01-06", value: 36, perc: 0.33}
  ]
  }]

奖金问题:我应该怎么做才能计算不同时间段(每两天、每星期等)的百分比变化并获得如下所示的输出? (每两天显示百分比变化)

data =[
  {
  key: "london",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-03", value: 30, perc: 2},
   {day: "2020-01-05", value: 30, perc: 0},
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-03", value: 30, perc: 2},
   {day: "2020-01-05", value: 30, perc: 0},
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", value: 10, perc: 0},
   {day: "2020-01-03", value: 6, perc: -0.4},
   {day: "2020-01-05", value: 27, perc: 4.5},
  ]
  }]

这是我对这种情况的看法。它还包括奖金问题。

P.S.: 这是我的第一个Whosebugpost,有什么问题欢迎追问!

// Your input data
const data = [
  {
  key: "london",
  values: [
   {day: "2020-01-01", city: "london", value: 10},
   {day: "2020-01-02", city: "london", value: 20},
   {day: "2020-01-03", city: "london", value: 30},
   {day: "2020-01-04", city: "london", value: 30},
   {day: "2020-01-05", city: "london", value: 30},
   {day: "2020-01-06", city: "london", value: 30}
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", city: "berlin", value: 10},
   {day: "2020-01-02", city: "berlin", value: 15},
   {day: "2020-01-03", city: "berlin", value: 30},
   {day: "2020-01-04", city: "berlin", value: 30},
   {day: "2020-01-05", city: "berlin", value: 30},
   {day: "2020-01-06", city: "berlin", value: 45}
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", city: "rome", value: 10},
   {day: "2020-01-02", city: "rome", value: 12},
   {day: "2020-01-03", city: "rome", value: 6},
   {day: "2020-01-04", city: "rome", value: 9},
   {day: "2020-01-05", city: "rome", value: 27},
   {day: "2020-01-06", city: "rome", value: 36}
  ]
}];

// The parsed output data
const parsedData = data.map((obj) => {
  // Maps the object values to calculate the percentage
  return {...obj, values: obj.values.map((value, i) => {
    // Delete the "city" key
    delete value['city'];

    // Can't calculate the percentage on the first element
    if (i == 0)
       return { ...value, perc: 0 };

    // Get the current & previous day/value
    const currentValue = value.value;
    const currentDay = new Date(value.day);

    const previousValue = obj.values[i-1].value;
    const previousDay = new Date(obj.values[i-1].day);

    // Calculate the days between the previous and current entry
    const dayTimeDiff = Math.abs(currentDay - previousDay);
    const dayDiff = Math.ceil(dayTimeDiff / (1000 * 60 * 60 * 24));

    // Calculate the precentage = (current - previous) / previous
    const percentDiff = currentValue - previousValue / previousValue / dayDiff;
    
    return { ...value, perc: percentDiff };
  })}
});

console.log(parsedData);

对于第一部分,您可以操作值数组中的每个值:

const data = [
  {
  key: "london",
  values: [
   {day: "2020-01-01", city: "london", value: 10},
   {day: "2020-01-02", city: "london", value: 20},
   {day: "2020-01-03", city: "london", value: 30},
   {day: "2020-01-04", city: "london", value: 30},
   {day: "2020-01-05", city: "london", value: 30},
   {day: "2020-01-06", city: "london", value: 30}
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", city: "berlin", value: 10},
   {day: "2020-01-02", city: "berlin", value: 15},
   {day: "2020-01-03", city: "berlin", value: 30},
   {day: "2020-01-04", city: "berlin", value: 30},
   {day: "2020-01-05", city: "berlin", value: 30},
   {day: "2020-01-06", city: "berlin", value: 45}
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", city: "rome", value: 10},
   {day: "2020-01-02", city: "rome", value: 12},
   {day: "2020-01-03", city: "rome", value: 6},
   {day: "2020-01-04", city: "rome", value: 9},
   {day: "2020-01-05", city: "rome", value: 27},
   {day: "2020-01-06", city: "rome", value: 36}
  ]
  }]

const newData = data.map((info) => {

      const n = info.values.length;
      const valuesCopy = info.values.map((info) => info.value);

      for (let i = 0; i < n; i++) {

         const currentValue = valuesCopy[i];
         const previousValue = valuesCopy[i - 1];
         // calculate the percentage
         const percentage = (currentValue - previousValue) / previousValue;

        // percentage is NaN return 0
        // percentage is < 1, return 2 decimal places
        // otherwise return percentage
        info.values[i].value = !percentage ? 0 : percentage < 1 ? percentage.toFixed(2) : percentage;
      }

    return info;
  })

 console.log(JSON.stringify(newData, null, 2));

使用简单 for 循环 + 注释的示例:

const data =[
  {
  key: "london",
  values: [
   {day: "2020-01-01", city: "london", value: 10},
   {day: "2020-01-02", city: "london", value: 20},
   {day: "2020-01-03", city: "london", value: 30},
   {day: "2020-01-04", city: "london", value: 30},
   {day: "2020-01-05", city: "london", value: 30},
   {day: "2020-01-06", city: "london", value: 30}
  ]
  },
  {
  key: "berlin",
  values: [
   {day: "2020-01-01", city: "berlin", value: 10},
   {day: "2020-01-02", city: "berlin", value: 15},
   {day: "2020-01-03", city: "berlin", value: 30},
   {day: "2020-01-04", city: "berlin", value: 30},
   {day: "2020-01-05", city: "berlin", value: 30},
   {day: "2020-01-06", city: "berlin", value: 45}
  ]
  },
  {
  key: "rome",
  values: [
   {day: "2020-01-01", city: "rome", value: 10},
   {day: "2020-01-02", city: "rome", value: 12},
   {day: "2020-01-03", city: "rome", value: 6},
   {day: "2020-01-04", city: "rome", value: 9},
   {day: "2020-01-05", city: "rome", value: 27},
   {day: "2020-01-06", city: "rome", value: 36}
  ]
  }
];

// Define resulting array
const results = [];

// Loop data
for(let i = 0; i < data.length; i++) {
  // Set city object
  const city = {
    key: data[i].key,
    values: []
  };
  
  // Set shorcut to values
  const dVal = data[i].values
  
  // Loop values in city entry
  for(let i = 0; i < dVal.length; i++) {
    // Set previous value or current if it is first cycle
    const prev = (i !== 0) ? dVal[i-1].value : dVal[i].value;
    // Set current value
    const cur = dVal[i].value;
    // Calculate percentage
    let percDiff = (cur - prev) / prev;
    // Fancy result as you need
    percDiff = parseFloat(percDiff.toFixed(2));
    // Push to city object
    city.values.push({
      day: dVal[i].day,
      value: dVal[i].value,
      perc: percDiff
    });
  }
  
  // Push city object to resulting array
  results.push(city);
}

// Log
console.log(results);

第二个问题的答案很简单——从数组中删除不需要的日条目,并将生成的数组传递给同一个函数。它计算条目之间的差异,无论是天还是周