如何将散点图与复杂数据一起使用?

时间:2017-06-30 09:57:53

标签: javascript dc.js crossfilter

我尝试按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

enter image description here

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

1 个答案:

答案 0 :(得分:1)

我仍然不相信这是值得的,而不是咬紧牙关,压扁你的数据并修复其他图表。如果你的数据不平坦,你将在每一步都与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)。一旦我们过去了,这个小组很简单。

图表将根据用户密钥分配符号和颜色。这些都是一样的;序数比例将为其在域中遇到的每个新值分配一个新值。唯一的区别是我们使用的是默认色标,而我们必须指定自己的符号比例。

这是一个小提琴:https://jsfiddle.net/gordonwoodhull/3m4mv3xf/19/