使用嵌套 json 数据创建多行

Creating multiples lines using a nested json data

我有一个像这样的嵌套 json:

(47) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0:
day: "2020-03-14"
total:
confirmed: 81
recovered: 9
deaths: 2
active: 70
__proto__: Object
statewise: Array(37)
0:
state: "Andaman and Nicobar Islands"
confirmed: 0
recovered: 0
deaths: 0
active: 0
__proto__: Object
1: {state: "Andhra Pradesh", confirmed: 1, recovered: 0, deaths: 0, active: 1}
.......

结构是这样的:

<array consiting daywise data>
    day
    total
     -confirmed
     -recovered
     -deaths
     -active
    statewise
       <array defining states having below items>
           - state
           - confirmed
           - recovered
           - deaths

事实是,我想制作一个折线图,显示总病例数(已确认)趋势以及如下状态的日期:

代码:

  <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.7/crossfilter.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dc/3.2.1/dc.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/reductio/1.0.0/reductio.js"></script>

 <script>

  const cases_chart = dc.lineChart("#line-chart");
  var log = console.log; 
  d3.json('https://api.rootnet.in/covid19-in/unofficial/covid19india.org/statewise/history').then(function(json_data) {
  var data = json_data.data.history;
  log("=====>", data);

    cf = crossfilter(data); // Main crossfilter objects
    var cases_bar_d = cf.dimension(function(d) { 
      console.log('---------------------->',new Date(d.day));
      return d.day});

    var cases_bar_g = cases_bar_d.group().reduceSum(function(d){ 
      log("statewise:", d.statewise);

      return d.statewise});
   });
</script>

实际上状态中有 37 个项目,我知道如何解决这个解决方案。我必须创建一个复合图表。但是创建 37 个组然后将它们提供给复合图表将是一个漫长的过程。还有其他方法可以解决这个问题吗?我可以通过返回 d.statewise[0].confirmed,.....d.statewise[36].confirmed

单独创建组

我想cases_bar_g变成这样:

{key: <date>, <state_name1>: <confirmed1>, .....<state_name36>: <confirmed36> }

然后创建图表会更容易。

编辑 1:

我好像发现了一个具有相同嵌套模式的 similar 问题。但是很难将其实现为折线图。

编辑2:

我设法将阵列展平用于州确诊病例。

    data.forEach(function(d,i){

      log("!!!!", i);

      for (var j=0; j<d.statewise.length;j++)
      {
          log("@@@:",map_state[d.statewise[j].state],d.statewise[j].state , d.statewise[j].confirmed);

         d[map_state[d.statewise[j].state]] = d.statewise[j].confirmed;
     }
   });

现在看起来像这样:

虽然现在我可以直接访问元素来绘制它。但我认为这不是一个好方法。我应该通过维度和组概念来完成它。

在处理交叉过滤器时,展平通常是个好主意。它应该可以正常工作,并且可能不会影响性能。

但我同意这里可能没有必要。

您应该能够使用自定义缩减从 statewise 数组中读取数据并更新每个 bin 中值对象的多个字段。

在我的脑海中浮现,无法测试,也许是这样的

var cases_bar_g = cases_bar_d.group().reduce(
  // add
  (p, v) =>
    (v.statewise.forEach(({state, confirmed}) => p[state] = (p[state] || 0) + confirmed), p),
  // remove
  (p,v) =>
    (v.statewise.forEach(({state, confirmed}) => p[state] -= confirmed), p),
  // init
  () => ({})
);

现在我看了一下,它并不比展平更简单,但我同意它 "nicer" 不知何故。

我们告诉crossfilter:

  • 每个 bin 应该用一个空对象初始化
  • 每次向 bin 添加一行时,遍历 statewise 并在 bin 的值对象中为该 state 创建或添加一个条目,从 0 开始并递增 confirmed
  • 每次删除一行时,将 state 递减 confirmed

使用循环构建复合

如果您继续沿着这条路走下去而不是使用系列图表,为组合创建子图表仍然很容易。

您只需要一组州名,您可以从第一行中提取:

const states = data[0].statewise.map(d => d.state);

所有子图表将使用相同的维度和组;我们将只使用不同的值访问器来提取数据。

我们会将州名称映射到一组子图表并组合它们:

composite.compose(states.map(
  state => dc.lineChart(composite)
    .dimension(cases_bar_d)
    .group(cases_bar_g)
    .valueAccessor(kv => kv.value[state])
    // need .x() and .xUnits and such here
));