在 dc.js 中按多个维度递归分组?
Group by multiple dimensions recursively in dc.js?
dc.js 很棒,现在我正在尝试了解如何将它用于多维数据。
我有时间序列数据 (csv),其中包含给定日期符合特定属性的人数 - 例如65 岁以上棕色头发的人数。它的简化版本看起来像这样(头发颜色有 5 个选项,年龄段有 5 个选项,大约 200 个日期):
Date, Hair Color, 0-18, 19-39, 40-64, 65+
1/1/21, Brown, 5, 3, 10, 2
1/1/21, Blonde, 15, 2, 4, 1
1/2/21, Brown, 2, 8, 0, 2
1/2/21, Blonde, 11, 6, 7, 4
...
我希望能够绘制每个亚群随时间推移的累积计数。复杂的是我想展示
- 按头发颜色聚合的图
(所有年龄组的总和),然后可以切换(最好通过单击其中一行)显示:
- 给定头发颜色的绘图
按年龄组分类。
(请注意,在模型中,我将计数标准化以将其显示为累积百分比。我一直在使用 valueAccessors 直接进行计算。)
我的问题是:如何创建维度和组来创建这些图?
我不想为每个年龄组创建单独的变量(我希望它足够通用以扩展到更精细的类别)。但是我无法理解如何使用 reduce 和过滤器来实现我想要的结果。
此外,我应该将所有这些都作为复合图表中的折线图还是系列图表来完成?我计划添加额外的皱纹,然后使用从 d3 添加的额外趋势线对图表进行注释。
谢谢!
系列图表是一种方便工具class,可以在下方生成复合图表。
它允许您使用二维键指定数据,其中一个组件是用于图表中 X 值的键,一个组件是另一个键,用于将数据拆分为多个层- 线,在你的情况下。您还以 returns 部分初始化图表的函数形式为它提供了图层图表的“原型”。
听起来你的方向是正确的,所以我不会试图给出一个完整的答案,只是一些提示。欢迎大家在评论中跟进,我会编辑这个答案来补充细节。
扁平化数据
您可能希望将数据展平,以便每行只有一个值,即使用 Age 列和 Value 列来构建它。这是使用交叉过滤器的一般最佳实践。
您可以直接使用数据,但是
- 您将无法按年龄过滤,因为交叉过滤器中的过滤是按行
- 跨年龄汇总会更复杂,需要自定义缩减
使用多键和系列图表
在 series chart example 之后,您可以将维度定义为
const colorDateDimension = cf.dimension(d => [d['Hair Color'], d.Date]);
现在这个维度上的任何组都将按头发颜色和日期聚合。
现在,如果您使用系列图表,您可以使用
提取组件
chart
.seriesAccessor(({key}) => key[0])
.keyAccessor(({key}) => key[1])
您可以使用图层的系列图表chart function to determine the color or dash style的第三个参数,例如:
const dashStyles = {
'0-18': [3,1],
'19-29': [4,1,1,1],
// ...
};
.chart(function(c, _, subkey) {
return new dc.LineChart(c).dashStyle(dashStyles[subkey]);
})
互动
dc.js 本身不支持您所描述的那种向下钻取。有一个按头发颜色分类的图表和另一个按年龄分类的图表会更容易。然后当没有选择发色时,年龄表会显示所有发色,当没有选择年龄时,发色表会显示所有年龄。
如果您想要像您描述的那样向下钻取,则必须编写自定义代码来应用过滤器并在单击头发颜色时交换图表定义。它不是非常复杂,但如果您无法理解,请提出后续问题 - 最好将 SO 问题放在一个主题上。
使用 D3 注释
无论您如何实现图表,这部分都非常简单。
您将实现一个 pretransition
处理程序并使用 chart.selectAll
添加您需要的内容。 SO这里有很多例子,这里就不赘述了。
结论
我希望这能让你开始。我已经回答了您的具体问题,并就您问题中的其他假设或隐含问题给出了一些提示。要得到你想要的结果会有些工作,但绝对有可能。
dc.js 很棒,现在我正在尝试了解如何将它用于多维数据。
我有时间序列数据 (csv),其中包含给定日期符合特定属性的人数 - 例如65 岁以上棕色头发的人数。它的简化版本看起来像这样(头发颜色有 5 个选项,年龄段有 5 个选项,大约 200 个日期):
Date, Hair Color, 0-18, 19-39, 40-64, 65+
1/1/21, Brown, 5, 3, 10, 2
1/1/21, Blonde, 15, 2, 4, 1
1/2/21, Brown, 2, 8, 0, 2
1/2/21, Blonde, 11, 6, 7, 4
...
我希望能够绘制每个亚群随时间推移的累积计数。复杂的是我想展示
- 按头发颜色聚合的图
(所有年龄组的总和),然后可以切换(最好通过单击其中一行)显示:
- 给定头发颜色的绘图
按年龄组分类。
(请注意,在模型中,我将计数标准化以将其显示为累积百分比。我一直在使用 valueAccessors 直接进行计算。)
我的问题是:如何创建维度和组来创建这些图?
我不想为每个年龄组创建单独的变量(我希望它足够通用以扩展到更精细的类别)。但是我无法理解如何使用 reduce 和过滤器来实现我想要的结果。
此外,我应该将所有这些都作为复合图表中的折线图还是系列图表来完成?我计划添加额外的皱纹,然后使用从 d3 添加的额外趋势线对图表进行注释。
谢谢!
系列图表是一种方便工具class,可以在下方生成复合图表。
它允许您使用二维键指定数据,其中一个组件是用于图表中 X 值的键,一个组件是另一个键,用于将数据拆分为多个层- 线,在你的情况下。您还以 returns 部分初始化图表的函数形式为它提供了图层图表的“原型”。
听起来你的方向是正确的,所以我不会试图给出一个完整的答案,只是一些提示。欢迎大家在评论中跟进,我会编辑这个答案来补充细节。
扁平化数据
您可能希望将数据展平,以便每行只有一个值,即使用 Age 列和 Value 列来构建它。这是使用交叉过滤器的一般最佳实践。
您可以直接使用数据,但是
- 您将无法按年龄过滤,因为交叉过滤器中的过滤是按行
- 跨年龄汇总会更复杂,需要自定义缩减
使用多键和系列图表
在 series chart example 之后,您可以将维度定义为
const colorDateDimension = cf.dimension(d => [d['Hair Color'], d.Date]);
现在这个维度上的任何组都将按头发颜色和日期聚合。
现在,如果您使用系列图表,您可以使用
提取组件chart
.seriesAccessor(({key}) => key[0])
.keyAccessor(({key}) => key[1])
您可以使用图层的系列图表chart function to determine the color or dash style的第三个参数,例如:
const dashStyles = {
'0-18': [3,1],
'19-29': [4,1,1,1],
// ...
};
.chart(function(c, _, subkey) {
return new dc.LineChart(c).dashStyle(dashStyles[subkey]);
})
互动
dc.js 本身不支持您所描述的那种向下钻取。有一个按头发颜色分类的图表和另一个按年龄分类的图表会更容易。然后当没有选择发色时,年龄表会显示所有发色,当没有选择年龄时,发色表会显示所有年龄。
如果您想要像您描述的那样向下钻取,则必须编写自定义代码来应用过滤器并在单击头发颜色时交换图表定义。它不是非常复杂,但如果您无法理解,请提出后续问题 - 最好将 SO 问题放在一个主题上。
使用 D3 注释
无论您如何实现图表,这部分都非常简单。
您将实现一个 pretransition
处理程序并使用 chart.selectAll
添加您需要的内容。 SO这里有很多例子,这里就不赘述了。
结论
我希望这能让你开始。我已经回答了您的具体问题,并就您问题中的其他假设或隐含问题给出了一些提示。要得到你想要的结果会有些工作,但绝对有可能。