使用嵌套 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
));
我有一个像这样的嵌套 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
));