复杂数据如何使用散点图?
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
)。一旦我们过去了,小组就很简单了。
图表将根据用户键分配符号和颜色。它们的工作原理相同;序数标度将为它在域中遇到的每个新值分配一个范围内的新值。唯一的区别是我们使用默认的色标,而我们必须指定我们自己的符号标尺。
我正在尝试通过 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
)。一旦我们过去了,小组就很简单了。
图表将根据用户键分配符号和颜色。它们的工作原理相同;序数标度将为它在域中遇到的每个新值分配一个范围内的新值。唯一的区别是我们使用默认的色标,而我们必须指定我们自己的符号标尺。