crossfilter "double grouping" 其中key是另一个reduction的值
crossfilter "double grouping" where key is the value of another reduction
这是我关于 mac 地址的数据。每分钟记录一次。每分钟,我都有许多唯一的 Mac 个地址。
mac_add,created_time
18:59:36:12:23:33,2016-12-07 00:00:00.000
1c:e1:92:34:d7:46,2016-12-07 00:00:00.000
2c:f0:ee:86:bd:51,2016-12-07 00:00:00.000
5c:cf:7f:d3:2e:ce,2016-12-07 00:00:00.000
...
18:59:36:12:23:33,2016-12-07 00:01:00.000
1c:cd:e5:1e:99:78,2016-12-07 00:01:00.000
1c:e1:92:34:d7:46,2016-12-07 00:01:00.000
5c:cf:7f:22:01:df,2016-12-07 00:01:00.000
5c:cf:7f:d3:2e:ce,2016-12-07 00:01:00.000
...
我想使用 dc.js 和交叉过滤器创建 2 个条形图。图表请参考图片
第一个条形图很容易创建。它是可刷的。我创建了“created_time”维度,并通过“mac_add”创建了一个组和 reduceCount,如下所示:
var moveTime = ndx.dimension(function (d) {
return d.dd; //# this is the created_time
});
var timeGroup = moveTime.group().reduceCount(function (d) {
return d.mac_add;
});
var visitorChart = dc.barChart('#visitor-no-bar');
visitorChart.width(990)
.height(350)
.margins({ top: 0, right: 50, bottom: 20, left: 40 })
.dimension(moveTime)
.group(timeGroup)
.centerBar(true)
.gap(1)
.elasticY(true)
.x(d3.time.scale().domain([new Date(2016, 11, 7), new Date(2016, 11, 13)]))
.round(d3.time.minute.round)
.xUnits(d3.time.minute);
visitorChart.render();
问题出在第二个条形图上。我的想法是,一行数据等于 1 分钟,因此我可以聚合和总结每个 mac 地址的所有分钟,以获得每个 mac 地址的时间长度,方法是通过“创建另一个维度” mac_add”并对“mac_add”执行 reduceCount 以获得时间长度。然后目标是将时间长度按 30 分钟分组。所以我们可以得到有多少 mac 时间长度不超过 30 分钟的地址,有多少 mac_add 时间长度在 30 分钟到 1 小时之间,有多少 mac_add 有时间长度在 1 小时到 1.5 小时之间,等等...
如有错误请指正。从逻辑上讲,我在想第二个条形图的维度应该是时间长度的组(比如<30、<1hr、<1.5hr等)。但是时间长度组本身是不固定的。这取决于第一个图表的画笔选择。也许只有30分钟,也许只有1.5小时,也许有1.5小时和2小时等等...
所以我真的很困惑将什么参数放入第二个条形图中。以及获取所需参数的方法(如何对分组数据进行分组)。请帮我解释一下解决方法。
此致,
马文
我想我们过去曾将其称为 "double grouping",但我找不到之前的问题。
设置群组
我将从 mac 地址的常规交叉过滤器组开始,然后生成一个假组以按分钟数聚合。
var minutesPerMacDim = ndx.dimension(function(d) { return d.mac_add; }),
minutesPerMapGroup = minutesPerMacDim.group();
function bin_keys_by_value(group, bin_value) {
var _bins;
return {
all: function() {
var bins = {};
group.all().forEach(function(kv) {
var valk = bin_value(kv.value);
bins[valk] = bins[valk] || [];
bins[valk].push(kv.key);
});
_bins = bins;
// note: Object.keys returning numerical order here might not
// work everywhere, but I couldn't find a browser where it didn't
return Object.keys(bins).map(function(bin) {
return {key: bin, value: bins[bin].length};
})
},
bins: function() {
return _bins;
}
};
}
function bin_30_mins = function(v) {
return 30 * Math.ceil(v/30);
}
var macsPerMinuteCount = bin_keys_by_value(minutesPerMacGroup);
这将保留每个时间段的 mac 地址,我们稍后需要使用这些地址进行过滤。将 non-standard 方法 bins
添加到假组并不常见,但我想不出一种有效的方法来保留该信息,因为过滤接口只会让我们访问密钥。
由于该函数采用分箱函数,我们甚至可以使用 threshold scale if we wanted more complicated bins than just rounding up to the nearest 30 minutes. A quantize scale 是一种更通用的方法来进行如上所示的舍入。
设置图表
使用这些数据来驱动图表很简单:我们可以像往常一样使用维度和假组。
chart
.dimension(minutesPerMacDim)
.group(macsPerMinuteCount)
设置图表以便过滤有点复杂:
chart.filterHandler(function(dimension, filters) {
if(filters.length === 0)
dimension.filter(null);
else {
var bins = chart.group().bins(); // retrieve cached bins
var macs = filters.map(function(key) { return bins[key]; })
macs = Array.prototype.concat.apply([], macs);
var macset = d3.set(macs);
dimension.filterFunction(function(key) {
return macset.has(key);
})
}
})
回想一下,我们正在使用以 mac 地址为关键字的维度;这很好,因为我们要过滤 mac 个地址。但是图表正在接收 minute-counts 作为其键,filters
将包含这些键,如 30
、60
、90
等。所以我们需要提供一个 filterHandler,它接受 minute-count 个键并根据这些键过滤维度。
注意 1:这都是未经测试的,所以如果它不起作用,请 post 作为 fiddle 或 bl.ock 的示例 - 有 fiddle s 和块你可以 fork 开始 on the main page.
注2:严格来说,这不是测量连接时长:它是计算连接的总分钟数。不确定这对您是否重要。如果用户断开连接然后在时间范围内重新连接,则这两个会话将被计为一个。我认为您必须进行预处理才能获得持续时间。
编辑:根据您的 fiddle(谢谢!),上面的代码似乎确实有效。这只是正确设置 x 比例和 xUnits
的问题。
chart2
.x(d3.scale.linear().domain([60,1440]))
.xUnits(function(start, end) {
return (end-start)/30;
})
线性刻度在这里就可以了——我不会尝试量化 那个 刻度,因为已经设置了 30 分钟的刻度。我们确实需要设置 xUnits
以便 dc.js 知道制作条形图的宽度。
我不确定为什么 elasticX
在这里不起作用,但是 <30
垃圾箱让其他所有东西都相形见绌,所以我认为最好不要考虑它。
你的 fiddle 的分支:https://jsfiddle.net/gordonwoodhull/2a8ow1ay/2/
这是我关于 mac 地址的数据。每分钟记录一次。每分钟,我都有许多唯一的 Mac 个地址。
mac_add,created_time
18:59:36:12:23:33,2016-12-07 00:00:00.000
1c:e1:92:34:d7:46,2016-12-07 00:00:00.000
2c:f0:ee:86:bd:51,2016-12-07 00:00:00.000
5c:cf:7f:d3:2e:ce,2016-12-07 00:00:00.000
...
18:59:36:12:23:33,2016-12-07 00:01:00.000
1c:cd:e5:1e:99:78,2016-12-07 00:01:00.000
1c:e1:92:34:d7:46,2016-12-07 00:01:00.000
5c:cf:7f:22:01:df,2016-12-07 00:01:00.000
5c:cf:7f:d3:2e:ce,2016-12-07 00:01:00.000
...
我想使用 dc.js 和交叉过滤器创建 2 个条形图。图表请参考图片
第一个条形图很容易创建。它是可刷的。我创建了“created_time”维度,并通过“mac_add”创建了一个组和 reduceCount,如下所示:
var moveTime = ndx.dimension(function (d) {
return d.dd; //# this is the created_time
});
var timeGroup = moveTime.group().reduceCount(function (d) {
return d.mac_add;
});
var visitorChart = dc.barChart('#visitor-no-bar');
visitorChart.width(990)
.height(350)
.margins({ top: 0, right: 50, bottom: 20, left: 40 })
.dimension(moveTime)
.group(timeGroup)
.centerBar(true)
.gap(1)
.elasticY(true)
.x(d3.time.scale().domain([new Date(2016, 11, 7), new Date(2016, 11, 13)]))
.round(d3.time.minute.round)
.xUnits(d3.time.minute);
visitorChart.render();
问题出在第二个条形图上。我的想法是,一行数据等于 1 分钟,因此我可以聚合和总结每个 mac 地址的所有分钟,以获得每个 mac 地址的时间长度,方法是通过“创建另一个维度” mac_add”并对“mac_add”执行 reduceCount 以获得时间长度。然后目标是将时间长度按 30 分钟分组。所以我们可以得到有多少 mac 时间长度不超过 30 分钟的地址,有多少 mac_add 时间长度在 30 分钟到 1 小时之间,有多少 mac_add 有时间长度在 1 小时到 1.5 小时之间,等等...
如有错误请指正。从逻辑上讲,我在想第二个条形图的维度应该是时间长度的组(比如<30、<1hr、<1.5hr等)。但是时间长度组本身是不固定的。这取决于第一个图表的画笔选择。也许只有30分钟,也许只有1.5小时,也许有1.5小时和2小时等等...
所以我真的很困惑将什么参数放入第二个条形图中。以及获取所需参数的方法(如何对分组数据进行分组)。请帮我解释一下解决方法。
此致, 马文
我想我们过去曾将其称为 "double grouping",但我找不到之前的问题。
设置群组
我将从 mac 地址的常规交叉过滤器组开始,然后生成一个假组以按分钟数聚合。
var minutesPerMacDim = ndx.dimension(function(d) { return d.mac_add; }),
minutesPerMapGroup = minutesPerMacDim.group();
function bin_keys_by_value(group, bin_value) {
var _bins;
return {
all: function() {
var bins = {};
group.all().forEach(function(kv) {
var valk = bin_value(kv.value);
bins[valk] = bins[valk] || [];
bins[valk].push(kv.key);
});
_bins = bins;
// note: Object.keys returning numerical order here might not
// work everywhere, but I couldn't find a browser where it didn't
return Object.keys(bins).map(function(bin) {
return {key: bin, value: bins[bin].length};
})
},
bins: function() {
return _bins;
}
};
}
function bin_30_mins = function(v) {
return 30 * Math.ceil(v/30);
}
var macsPerMinuteCount = bin_keys_by_value(minutesPerMacGroup);
这将保留每个时间段的 mac 地址,我们稍后需要使用这些地址进行过滤。将 non-standard 方法 bins
添加到假组并不常见,但我想不出一种有效的方法来保留该信息,因为过滤接口只会让我们访问密钥。
由于该函数采用分箱函数,我们甚至可以使用 threshold scale if we wanted more complicated bins than just rounding up to the nearest 30 minutes. A quantize scale 是一种更通用的方法来进行如上所示的舍入。
设置图表
使用这些数据来驱动图表很简单:我们可以像往常一样使用维度和假组。
chart
.dimension(minutesPerMacDim)
.group(macsPerMinuteCount)
设置图表以便过滤有点复杂:
chart.filterHandler(function(dimension, filters) {
if(filters.length === 0)
dimension.filter(null);
else {
var bins = chart.group().bins(); // retrieve cached bins
var macs = filters.map(function(key) { return bins[key]; })
macs = Array.prototype.concat.apply([], macs);
var macset = d3.set(macs);
dimension.filterFunction(function(key) {
return macset.has(key);
})
}
})
回想一下,我们正在使用以 mac 地址为关键字的维度;这很好,因为我们要过滤 mac 个地址。但是图表正在接收 minute-counts 作为其键,filters
将包含这些键,如 30
、60
、90
等。所以我们需要提供一个 filterHandler,它接受 minute-count 个键并根据这些键过滤维度。
注意 1:这都是未经测试的,所以如果它不起作用,请 post 作为 fiddle 或 bl.ock 的示例 - 有 fiddle s 和块你可以 fork 开始 on the main page.
注2:严格来说,这不是测量连接时长:它是计算连接的总分钟数。不确定这对您是否重要。如果用户断开连接然后在时间范围内重新连接,则这两个会话将被计为一个。我认为您必须进行预处理才能获得持续时间。
编辑:根据您的 fiddle(谢谢!),上面的代码似乎确实有效。这只是正确设置 x 比例和 xUnits
的问题。
chart2
.x(d3.scale.linear().domain([60,1440]))
.xUnits(function(start, end) {
return (end-start)/30;
})
线性刻度在这里就可以了——我不会尝试量化 那个 刻度,因为已经设置了 30 分钟的刻度。我们确实需要设置 xUnits
以便 dc.js 知道制作条形图的宽度。
我不确定为什么 elasticX
在这里不起作用,但是 <30
垃圾箱让其他所有东西都相形见绌,所以我认为最好不要考虑它。
你的 fiddle 的分支:https://jsfiddle.net/gordonwoodhull/2a8ow1ay/2/