简体   繁体   English

为D3堆积条形图准备嵌套JSON数据

[英]Prepare nested JSON data for D3 stacked bar chart

I have nested JSON data where the first level of keys is activity types (ride, hike, etc.) and the second level is the year. 我有嵌套的JSON数据,其中第一级键是活动类型(骑行,加息等),第二级是年份。 Each year has a value (distance in kilometers). 每年都有一个值(以千米为单位的距离)。 My data structure looks like this: 我的数据结构如下所示: 在此输入图像描述

I want to draw a stacked bar chart like this http://bl.ocks.org/mstanaland/6100713 from my data. 我想从我的数据中绘制一个像http://bl.ocks.org/mstanaland/6100713这样的堆积条形图。 How can I bring my data in a structure which is suitable for a D3 stacked bar chart? 如何将数据放入适合D3堆积条形图的结构中?

This could be done as follows: 这可以按如下方式完成:

const data = [];
myData.forEach(a => a.values.forEach(v => {
    const element = data.find(e => e.year === v.key);
    if (element) {
        element[a.key] = v.values;
    } else {
        data.push({ year: v.key, [a.key]: v.values });
    }
}));

Based on @unminder's answer but just to get every property into the object: 基于@ unminder的答案,但只是为了让每个属性都进入对象:

Stakblitz example: https://stackblitz.com/edit/js-d5sitf Stakblitz示例: https ://stackblitz.com/edit/js-d5sitf

const entryArr = [
  {
    key: 'ride',
    values: [
      { key: '2008', value: 3234 },
      { key: '2009', value: 3234 },
      { key: '2010', value: 5000 },
      { key: '2011', value: 6000 },
      { key: '2012', value: 1456 },
      { key: '2013', value: 2453 }
    ]
  },
  {
    key: 'hike',
    values: [
      { key: '2006', value: 3234 },
      { key: '2009', value: 2420 },
      { key: '2010', value: 4530 },
      { key: '2011', value: 2000 },
      { key: '2012', value: 1900 },
      { key: '2013', value: 3700 }
    ]
  },
  {
    key: 'walk',
    values: [
      { key: '2009', value: 3001 },
      { key: '2010', value: 1090 },
      { key: '2011', value: 2020 },
      { key: '2012', value: 2000 },
      { key: '2013', value: 6000 }
    ]
  }
];

const getKeys = entryArr.map(x => x.key);
const result = [];
entryArr.forEach(a => a.values.forEach(v => {
  const element = result.find(e => e.year === v.key);
  if (element) {
    element[a.key] = v.value;
  } else {
    const obj = getKeys.reduce((acc, x) => ({ ...acc, year: v.key, [x]: a.key === x ? v.value : '' })
      , {});
    result.push(obj);
  }
}));

console.log(result)

Note: it can be improved using reducers to avoid global variables 注意:可以使用reducers来改进它以避免全局变量

This works good, but when combinations are missing, no entry is made, so it's not true wide data. 这很好用,但是当缺少组合时,不会进行任何输入,因此它不是真正的宽数据。 I achieved it with this code: 我用这段代码实现了它:

// make data long
var flatdata = []
            distance_per_year.forEach(function(type) {
              type.values.forEach(function(typeYears) {
                flatdata.push({
                  type: type.key,
                  year: typeYears.key,
                  distance: typeYears.values,
                });
              });
            });

    // Unique activity types
    groups = Array.from(new Set(flatdata.map(({ type }) => type)));
    years = Array.from(new Set(flatdata.map(({ year }) => year)));

    // make wide data with 0 where value is missing
    var grouped = years.map(function(d) {
      var item = {
        year:  d
      };
      groups.forEach(function(e) {
        var itemForGroup = flatdata.filter(function(f) {
          return f.type === e && f.year === d;
        });
        if (itemForGroup.length) {
          item[e] = Number(itemForGroup[0].distance);
        } else {
          item[e] = 0;
        }
      })
      return item;
    })

This produces first an unnested long dataset first (3 columns), then reshapes it to wide and fills in 0s where distance is missing. 这首先产生一个未经加工的长数据集(3列),然后将其重新整形为宽并填充0,其中距离缺失。

The source are these two questions: Reshape data for D3 stacked bar chart and d3: flatten nested data? 来源是这两个问题: 重塑D3堆积条形图的数据d3:展平嵌套数据?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM