复杂数据如何使用散点图?

How to use scatter chart with complex data?

我正在尝试通过 example 实现散点图。

在示例中我们可以看到创建维度:

runDimension = ndx.dimension(function(d) {return [+d.Expt, +d.Run]; });

示例数据:

Expt Run Speed
1    1   850
1    2   740
1    3   900

我想使用相同的图表,但我的数据采用下一种格式:

[
 {
  "Timestamp":"2016-12-15T17:29:53Z",
  "idgame":"euro",
  "users":{
    "Jo": {
      "energy":200,
      "jump_height":0.5
     },
    "Bob": {
      "energy":220,
      "jump_height":0.35
     }
  }
 },
 {
  "Timestamp":"2016-12-15T17:29:55Z",
  "idgame":"euro",
  "users":{
    "Jo": {
      "energy":120,
      "jump_height":0.15
     },
    "Bob": {
      "energy":240,
      "jump_height":0.75
     }
  }
 }
]

我需要构建下一个图表,其中 x 轴是 timestamp,y 轴是 jump_height:

我的数据已经在 crossfilter 中了,所以我无法更改它。 如何使用当前格式创建良好的维度?

我仍然不相信这是值得付出努力的,而不是硬着头皮压平数据并修复其他图表。如果您的数据不平坦,您将在每一步都与 crossfilter 和 dc.js 作斗争。

也就是说,像往常一样,这是可能的!

我们不能使用系列图表,因为这要求所有数据都出现在一组中。但是由于你想从每行数据中产生多个符号,一个普通的交叉过滤器组不能产生你需要的数据。

也许我们可以使用一个假的组,但这会很复杂。相反,让我们为每个用户生成一个维度和组,然后使用复合图表将它们缝合在一起。

首先,我们需要解析那些时间戳:

data.forEach(function(d) {
  d.Timestamp = new Date(d.Timestamp);
});

接下来,我们将检索所有用户的列表,方法是从每个事件(时间戳)中提取用户密钥,将它们连接起来,然后使用 d3.set 来唯一化它们:

// retrieve all users from all events
var users = data.reduce(function(p, event) {
  return p.concat(Object.keys(event.users));
}, []);
users = d3.set(users).values();

在其余代码中,我们假设每个事件都有相同的用户。它们可能不同,但会增加额外的复杂性,而这个答案已经足够复杂了。如果您需要该功能,请联系我!

我们将创建图表、交叉过滤器和一个将符号分配给用户的比例尺:

var chart = dc.compositeChart("#test");
var ndx = crossfilter(data);
var symbolScale = d3.scale.ordinal().range(d3.svg.symbolTypes);

现在我们可以创建复合图表了。 (我们将在下一步添加散点图。)

chart
  .width(768)
  .height(480)
  .x(d3.time.scale())
  .xUnits(d3.time.seconds)
  .elasticX(true)
  .elasticY(true)
  .brushOn(false)
  .clipPadding(10)
  .shareTitle(false) // allow default scatter title to work
  .shareColors(true) // but use different colors for subcharts
  .legend(dc.legend().x(350).y(350).itemHeight(13)
          .gap(5).horizontal(1).legendWidth(140).itemWidth(70));

我们在X轴上设置了时间刻度,分辨率为秒。两个轴都有弹性。我们需要共享颜色,以便为每个子图分配自己的颜色。 (图例可能被过度指定 - 我从另一个例子中复制了这个。)

我们终于进入正题了。对于每个用户,我们将创建一个子图表,我们将告诉复合图表来组合所有这些:

chart.compose(users.map(function(user) {
  var userDimension = ndx.dimension(function(d) {
    return [d.Timestamp, d.users[user].jump_height];
  })
  var jumpGroup = userDimension.group();
  console.log(user, jumpGroup.all());
  var scatter = dc.scatterPlot(chart)
    .symbol(symbolScale(user))
    .dimension(userDimension)
    .group(jumpGroup)
    .colorAccessor(function() { return user; })
    .symbolSize(8)
    .highlightedSize(10);
  return scatter;
}))

我们正在为每个图表创建一个新维度。这是因为 dc.js 散点图需要键同时包含 X 和 Y 坐标,而我们只有在了解用户后才能访问 Y 坐标 (jump_height)。一旦我们过去了,小组就很简单了。

图表将根据用户键分配符号和颜色。它们的工作原理相同;序数标度将为它在域中遇到的每个新值分配一个范围内的新值。唯一的区别是我们使用默认的色标,而我们必须指定我们自己的符号标尺。

这里是 fiddle:https://jsfiddle.net/gordonwoodhull/3m4mv3xf/19/