【问题标题】:dc.js Scatter Plot with multiple values for a single keydc.js 散点图,单个键具有多个值
【发布时间】:2017-12-22 01:11:49
【问题描述】:

我们的仪表板中的散点图效果很好,但我们被抛出了一个曲线球。我们有一个新数据集,它为单个键提供多个 y 值。如果发生这种情况,我们还有其他数据集,但我们先将数据展平,但我们不想展平此数据集。

散点图应该使用 x 轴的 uid 和 y 轴值的 inj 字段中的每个值。 inj 字段将始终是一个数字数组,但数组中的每一行可能有 1 .. n 个值。

var data = [
    {"uid":1, "actions": {"inj":[2,4,10], "img":[10,15,25], "res":[15,19,37]},
    {"uid":2, "actions": {"inj":[5,8,15], "img":[5,8,12],   "res":[33, 45,57]}
    {"uid":3, "actions": {"inj":[9],      "img":[2],        "res":[29]}
];

我们可以定义维度和组来绘制 inj 字段中的第一个值。

var ndx   = crossfilter(data);
var spDim = ndx.dimension(function(d){ return [d.uid, d.actions.inj[0]];});
var spGrp = spDim.group();

但是对于如何定义散点图以处理每个 x 值的多个 y 值有什么建议吗?

这是一个jsfiddle 示例,展示了我如何显示第一个元素或最后一个元素。但是如何显示数组的所有元素呢?

--- 附加信息 ---

以上只是一个演示需求的简单示例。我们开发了一个完全由数据驱动的动态数据浏览器。目前正在使用的数据集受到保护。我们将很快添加一个公共数据集来展示各种功能。下面是几张图片。

我隐藏了一些传说。对于散点图,我们添加了一个仅垂直的画笔,当按下“选择”按钮时会启用该画笔。注释部分在散点图初始化时填充整体数据集统计信息。然后,当执行任何过滤器时,注释部分会更新为仅过滤数据的统计信息。

字段选择树显示所选数据集的元数据。用户可以决定将哪些字段显示为图表和数据表(未显示)。目前对于显示的数据集,我们只有 89 个可用字段,但对于另一个数据集,用户可以混合和匹配 530 个字段。

我没有在图表 DIV 下方显示包含实际数据的多个数据表的各种选项卡。

元数据定义了几个字段以帮助动态构建资源管理器仪表板。

【问题讨论】:

  • Hrrrmmm,我记得与此相关的一些问题,但是 examples 中的 none 与 dc.js 的 included 似乎对此有问题,所以我很难记住是什么错误的。你能创造一个小提琴或类似的东西吗?
  • 哦,我想这可以归结为创建一个假组,该组可以将单行数据转换为散点图的多个输入。这与 x 值的多个 y 值无关。如果你可以扁平化你的数据,你会更开心,但假组是可能的。
  • 我在帖子中添加了一个 jsFiddle 示例。
  • 我正在调查它。一个警告:crossfilter 只能按给定数据中的行进行过滤,因此您将无法进行矩形选择,只能通过 UID 进行水平选择。更换刷子可能很棘手;首先,我将演示如何让输入与假组一起工作。

标签: javascript d3.js dc.js crossfilter


【解决方案1】:

我警告过你代码不会很漂亮!如果你可以扁平化你的数据,你可能会更开心,但它是可以做到的。

我们可以首先聚合每个uid 中的所有injs,方法是按数据中的行过滤并按uid 聚合。在减少中,我们计算每个 inj 值的实例:

        uidDimension = ndx.dimension(function (d) {
            return +d.uid;
        }),
        uidGroup = uidDimension.group().reduce(
            function(p, v) { // add
                v.actions.inj.forEach(function(i) {
                    p.inj[i] = (p.inj[i] || 0) + 1;
                });
                return p;
            },
            function(p, v) { // remove
                v.actions.inj.forEach(function(i) {
                    p.inj[i] = p.inj[i] - 1;
                    if(!p.inj[i])
                        delete p.inj[i];
                });
                return p;
            },
            function() { // init
                return {inj: {}};
            }
        );
        uidDimension = ndx.dimension(function (d) {
            return +d.uid;
        }),
        uidGroup = uidDimension.group().reduce(
            function(p, v) { // add
                v.actions.inj.forEach(function(i) {
                    p.inj[i] = (p.inj[i] || 0) + 1;
                });
                return p;
            },
            function(p, v) { // remove
                v.actions.inj.forEach(function(i) {
                    p.inj[i] = p.inj[i] - 1;
                    if(!p.inj[i])
                        delete p.inj[i];
                });
                return p;
            },
            function() { // init
                return {inj: {}};
            }
        );

这里我们假设可能存在具有相同uid 和不同inj 数组的数据行。这比您的示例数据所需的更为通用:如果每个 uid 确实只有一行数据,您可能会做一些更简单的事情。

为了展平结果组,我们可以使用"fake group" 为每个[uid, inj] 对创建一个类似组的{key, value} 数据项:

    function flatten_group(group, field) {
        return {
            all: function() {
                var ret = [];
                group.all().forEach(function(kv) {
                    Object.keys(kv.value[field]).forEach(function(i) {
                        ret.push({
                            key: [kv.key, +i],
                            value: kv.value[field][i]
                        });
                    })
                });
                return ret;
            }
        }
    }
    var uidinjGroup = flatten_group(uidGroup, 'inj');

Fork of your fiddle

在小提琴中,我添加了一个条形图来演示按 UID 进行过滤。条形图上的过滤有效,但散点图上的过滤无效。如果您需要在散点图上进行过滤,这可能是固定的,但它只能在uid 维度上进行过滤,因为您的数据太自然而无法通过inj 进行过滤。

【讨论】:

  • 如果您想在散点图上使用刷子,则需要像条形图那样使用水平刷子,而不是矩形选择。我很乐意解决这个问题,但我想我会先发布这个。
  • 哇,印象深刻。我在最初的帖子中添加了其他信息,开始详细说明此要求如何适应更大的图景。 注意: 每个 UID 只有一行数据,因为它是数据集中每一行的唯一标识符。我想我可以在我们的代码中动态地让它工作,但我需要让它与我们的散点图垂直画笔一起工作。
  • 我添加了一个 PieChart(使用新字段 [gender])并将 injCountGroup 更改为使用 uidDimension2 而不是 uidDimension。当我垂直过滤散点图(完全并排)但仅选择 y 轴 15 处的点时,它不会在饼图中描绘正确的数据(1 个男性,0 个女性)。啊!! jsfiddle fork
  • 一个男性是正确的,对吧?它选择了 UID 4。令我惊讶的是,散点图使用的 2D 过滤器有一个特殊情况,如果它检查的数据是标量,它只比较 X 坐标。所以我想这是故意的,虽然通常我不希望能够用 2D 画笔过滤 1D 维度。
  • 可能会强制画笔显示为 1D,在这种情况下会更加清晰。但我还没有研究过。
猜你喜欢
  • 2012-12-21
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多