Javascript 使用两组的dc.js Box plot reducer
我正在尝试生成一个方框图,它将显示单个设备连接到的网络总数,并按其供应商分组 数据格式:Javascript 使用两组的dc.js Box plot reducer,javascript,d3.js,dc.js,Javascript,D3.js,Dc.js,我正在尝试生成一个方框图,它将显示单个设备连接到的网络总数,并按其供应商分组 数据格式: { "SSID": "eduroam", "identifier": "Client", "latitude": 52.4505, "longitude": -1.9361, "mac": "dc:d9:16:##:##:##", "packet": "PR-REQ", "timestamp": "2018-07-10 12:25:26", "
{
"SSID": "eduroam",
"identifier": "Client",
"latitude": 52.4505,
"longitude": -1.9361,
"mac": "dc:d9:16:##:##:##",
"packet": "PR-REQ",
"timestamp": "2018-07-10 12:25:26",
"vendor": "Huawei Technologies Co.Ltd"
}
摆弄数据
我已经使用以下代码获得了单个设备连接到的网络的总和。之前过滤的数据只包含mac地址的唯一网络,因此使用计数器对网络进行计数
var mac = ndx.dimension(function (d) { return d["mac"]; });
var SSIDstoSingleMAC = mac.group().reduceSum(function (d) { return
+d.counter});
我的问题在于,试图将这个分组的和传递到另一个组中,该组将输出一个数组以用于方框图
var vendor = ndx.dimension(function (d) { return d["vendor"]; });
//Used to count number of networks per device
var mac = ndx.dimension(function (d) { return d["mac"]; });
var SSIDstoSingleMAC = mac.group().reduceSum(function (d) { return
+d.counter});
//This is where things fall down
var boxplotGroup = SSIDstoSingleMAC.group().reduce(
function (p, v) {
let dv = v.counter;
if (dv != null) p.push(dv);
return p;
},
function (p, v) {
let dv = v.counter;
if (dv != null) p.splice(p.indexOf(dv), 1);
return p;
},
function () {
return [];
}
);
var boxPlot = dc.boxPlot("#boxPlot");
boxPlot
.width(1200)
.height(600)
.dimension(vendor)
.group(boxplotGroup)
.tickFormat(d3.format('.1f'))
.elasticY(true)
.elasticX(true)
;
这就是目标:
例如苹果[7,5,10,2]=四台苹果设备。。设备1已连接到7个网络。。。发射型计算机断层扫描仪。。
尝试隐藏组
Gordon在评论中提到,两个组不能在crossfilter中递归传递。我现在正试图生成一个隐藏组,它可以使用DC git中的以下代码来累积每个mac地址的网络,但是我无法使其与boxplot reducer匹配。。我走的方向对吗
感谢Adam理想情况下,我们真的希望在这里对供应商使用一个简单的维度,以防我们想使用方框图上的画笔进行过滤 因此,问题变成了:我们如何减少两次,一次是获得每个MAC地址的计数,然后再次将这些计数转换为一个数组 第一部分有一个标准答案:只需简化为一个对象而不是一个值:
var vendorMacCountsGroup = vendor.group().reduce(
function(p, v) { // add
p[v.mac] = (p[v.mac] || 0) + v.counter;
return p;
},
function(p, v) { // remove
p[v.mac] -= v.counter;
return p;
},
function() { // init
return {}; // macs;
}
);
我最近描述了这种模式,所以这里不再详细介绍
以下是示例输出:箱子是供应商,每个值都是一个对象,将mac地址映射到计数:
[
{
"key": "Asustek Computer Inc.",
"value": {
"1c:b7:2c:48": 8,
"1c:b7:be:ef": 3
}
},
{
"key": "Huawei Technologies Co.Ltd",
"value": {
"dc:d9:16:3d": 14,
"dc:da:16:3d": 2,
"dc:d9:16:3a": 1,
"dc:d9:16:3b": 1
}
},
...
下一步,我们真的只需要计数,忘记MAC地址。JavaScript为此提供了一个很好的内置函数。我们只需要将其应用于我们组中的每个对象值。我们还将抛出任何零,因为只有当MAC地址在其他地方被过滤掉时,才会发生这种情况
function flatten_object_group(group) {
return {
all: function() {
return group.all().map(function(kv) {
return {
key: kv.key,
value: Object.values(kv.value).filter(function(v) { return v>0; })
};
});
}
};
}
var boxPlotGroup = flatten_object_group(vendorMacCountsGroup);
样本输出:
[
{
"key": "Asustek Computer Inc.",
"value": [
8,
3
]
},
{
"key": "Huawei Technologies Co.Ltd",
"value": [
14,
2,
1,
1
]
},
...
您的示例数据每个供应商只有一个MAC地址,因此我添加了一些虚假数据,得到了一个外观不错的箱线图:
仅在Mac公司排名前十
作为一个示例,如果有太多的框,您可能会如何修剪数据,下面是如何按MAC地址的数量进行排序,并仅选取10家“最受欢迎”的供应商:
按如下方式编写:
var boxPlotGroup = top_ten_by_length(flatten_object_group(vendorMacCountsGroup));
这是我的想法,未经测试,因此,如果有问题,请编辑/评论。是的,交叉过滤器中目前不存在双重分组。您可以创建一个以不同的方式减少数据的方法。或者,通常可以创建一个复杂的还原,在一次过程中完成所有操作。我不完全清楚你想做什么-我可能只是累了-但我只是想确认,是的,分组不是递归的。谢谢你的回答戈登,我将取消双重分组!我现在要看一看假团体,和减员们玩一玩。我喜欢胡说八道。。我只是尝试为方框图收集一个数组,其中包含单个设备连接到的网络的总数,然后我可以按制造商/供应商分组。例如苹果[7,5,10,2]=四台苹果设备。。设备1已连接到7个网络。。。发射型计算机断层扫描仪。。然后,我将继续我的数据中的其他制造商,并在我的问题中添加一些代码。我曾经尝试过实现这个伪组,以累积每个设备的网络数量,然后传递给box plot reducer,但我仍然没有运气。最后一个问题。。我保证。。有没有办法限制在方框图上绘制的条形图的数量?我有150多家供应商,所以除非我在其他地方做了选择,否则一切都在自己的基础上。我已经试过了。第(10)章,就像我在行图上做的一样,但似乎不起作用。感谢Adam,CSS有点奇怪-也许你使用的CSS版本比你使用的库更早。将3.x CSS与2.x库一起使用应该可以很好地工作。没错,.cap()仅在某些图表上可用。你可以用另一个包裹这个假团体。我不确定你想要什么样的标准,但我会在上面添加一个快速的例子。这非常适合将条形图限制为10!非常感谢你的帮助,戈登,我现在可以专注于数据收集和撰写报告了。。这是一个学习曲线,但我觉得我为下次使用dc做了更好的准备!添加了示例输出,以澄清数据形状和正在进行的操作。
function top_ten_by_length(group) {
return {
all: function() {
return group.all().sort(function(a,b) {
return b.value.length - a.value.length;
}).slice(0, 10);
}
};
}
var boxPlotGroup = top_ten_by_length(flatten_object_group(vendorMacCountsGroup));