具有 Non-Exclusive 属性的维度图表
Dimensional Charting with Non-Exclusive Attributes
以下是简化的示意图,table,显示了 HTTP 事务。我想使用 dc
为其构建 DC 分析,但某些列不能很好地映射到 crossfilter
。
在本题的设置中,所有的HTTP事务都有time
、host
、requestHeaders
、responseHeaders
、numBytes
字段。但是,不同的事务有不同的特定 HTTP 请求和响应 header。在上面的 table 中,0 和 1 分别表示特定交易中特定 header 的不存在和存在。 requestHeaders
和 responseHeaders
的 sub-columns 代表交易中存在的 header 的并集。不同的 HTTP 交易数据集几乎肯定会生成不同的 sub-columns.
对于这个问题,图表中的一行用这样的代码表示:
{
"time": 0,
"host": "a.com",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 0},
"numBytes": 12
}
time
、host
和 numBytes
都可以轻松转换为 crossfilter
,因此可以构建图表来回答诸如总数是多少这样的问题主机 a.com
的 2 到 4 之间事务的字节数。例如,
var ndx = crossfilter(data);
...
var hostDim = ndx.dimension(function(d) {
return d.host;
});
var hostBytes = hostDim.group().reduceSum(function(d) {
return d.numBytes;
});
问题是,对于 time
和 host
的所有切片,我想显示(前导)请求和响应的(上限)条形图 header s 字节。例如。 (见第一行),对于时间 0 和主机 a.com
,请求 header 的条形图应显示 bar
和 baz
各有 12。
有两个问题,一个是小问题,一个是大问题。
小问题
这不太适合 dc
,因为它是 one-directional。这些条形图应该针对其他切片进行更新,但它们不能用于切片本身。例如,您不应该能够 select bar
和 deselect baz
,并按字节查找主机的结果细分,因为这意味着什么:主机在有 bar
但没有 baz
的交易中?交易中的主机有 bar
并且有或没有 baz
?太不直观了。
如何使一些 dc
图表具有方向性。是通过一些禁用鼠标输入的技巧吗?
主要问题
与host
相反,foo
和bar
是non-exclusive。每个交易的主机要么是某物,要么是另一个,但交易的 header 可能包括 foo
和 bar
.
的任意组合
如何为 requestHeaders
定义交叉过滤器尺寸,然后如何使用 dc
?即
var ndx = crossfilter(data);
...
var requestHeadersDim = ndx.dimension(function(d) {
// What should go here?
});
通过查看 dc
的源代码破解了它(高效但非常不优雅)。可以扭曲 crossfilter
的含义来达到预期的效果。
最后的结果就在这个fiddle。它比问题稍微有限,因为 responseHeaders
的字段被硬编码为 foo
、bar
和 baz
。删除此限制更多是在简单 Javascript.
的领域
小问题
使用simple css hack,我简单定义了
.avoid-clicks {
pointer-events: none;
}
并给了 div 这个 class。不优雅但有效。
主要问题
主要问题是通过扭曲crossfilter
概念的意义来解决的,"fooling"dc
。
假设数据如下所示:
var transactions = [
{
"time": 0,
"host": "a.com",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 0},
"numBytes": 12
},
{
"time": 1,
"host": "b.org",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 1},
"numBytes": 3
},
...
];
我们可以定义一个"dummy"维度,忽略数据:
var transactionsNdx = crossfilter(transactions);
var dummyDim = transactionsNdx
.dimension(function(d) {
return 0;
});
使用这个维度,我们可以定义一个组来计算筛选行的总 foo
、bar
和 baz
字节:
var requestHeadersGroup = dummyDim
.group()
.reduce(
/* callback for when data is added to the current filter results */
function (p, v) {
return {
"foo": p.foo + v.requestHeaders.foo * v.numBytes,
"bar": p.bar + v.requestHeaders.bar * v.numBytes,
"baz": p.baz + v.requestHeaders.baz * v.numBytes,
}
},
/* callback for when data is removed from the current filter results */
function (p, v) {
return {
"foo": p.foo - v.requestHeaders.foo * v.numBytes,
"bar": p.bar - v.requestHeaders.bar * v.numBytes,
"baz": p.baz - v.requestHeaders.baz * v.numBytes,
}
},
/* initialize p */
function () {
return {
"foo": 0,
"bar": 0,
"baz": 0
}
}
);
请注意,这根本不是一个合适的 crossfilter
组。它不会将维度映射到它们的值。相反,它将 0 映射到一个值,该值本身将维度映射到它们的值(丑陋!)。因此,我们需要将这个组转换成实际上看起来像 crossfilter
组的东西:
var getSortedFromGroup = function() {
var all = requestHeadersGroup.all()[0].value;
all = [
{
"key": "foo",
"value": all.foo
},
{
"key": "bar",
"value": all.bar
},
{
"key": "foo",
"value": all.baz
}];
return all.sort(function(lhs, rhs) {
return lhs.value - rhs.value;
});
}
var requestHeadersDisplayGroup = {
"top": function(k) {
return getSortedFromGroup();
},
"all": function() {
return getSortedFromGroup();
},
};
我们现在可以创建常规 dc
图表,并传递适配器组
requestHeadersDisplayGroup
去吧。从此时开始它正常工作。
我通常处理您陈述的主要问题的方法是转换我的数据,以便每个 header 都有一个单独的记录(这些重复记录中的所有其他字段都是相同的)。然后我使用自定义组聚合来避免 double-counting。这些自定义聚合有点难以管理,所以我使用 'exception' 函数构建了 Reductionio 来帮助解决这个问题 - github.com/esjewett/reductio
以下是简化的示意图,table,显示了 HTTP 事务。我想使用 dc
为其构建 DC 分析,但某些列不能很好地映射到 crossfilter
。
在本题的设置中,所有的HTTP事务都有time
、host
、requestHeaders
、responseHeaders
、numBytes
字段。但是,不同的事务有不同的特定 HTTP 请求和响应 header。在上面的 table 中,0 和 1 分别表示特定交易中特定 header 的不存在和存在。 requestHeaders
和 responseHeaders
的 sub-columns 代表交易中存在的 header 的并集。不同的 HTTP 交易数据集几乎肯定会生成不同的 sub-columns.
对于这个问题,图表中的一行用这样的代码表示:
{
"time": 0,
"host": "a.com",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 0},
"numBytes": 12
}
time
、host
和 numBytes
都可以轻松转换为 crossfilter
,因此可以构建图表来回答诸如总数是多少这样的问题主机 a.com
的 2 到 4 之间事务的字节数。例如,
var ndx = crossfilter(data);
...
var hostDim = ndx.dimension(function(d) {
return d.host;
});
var hostBytes = hostDim.group().reduceSum(function(d) {
return d.numBytes;
});
问题是,对于 time
和 host
的所有切片,我想显示(前导)请求和响应的(上限)条形图 header s 字节。例如。 (见第一行),对于时间 0 和主机 a.com
,请求 header 的条形图应显示 bar
和 baz
各有 12。
有两个问题,一个是小问题,一个是大问题。
小问题
这不太适合 dc
,因为它是 one-directional。这些条形图应该针对其他切片进行更新,但它们不能用于切片本身。例如,您不应该能够 select bar
和 deselect baz
,并按字节查找主机的结果细分,因为这意味着什么:主机在有 bar
但没有 baz
的交易中?交易中的主机有 bar
并且有或没有 baz
?太不直观了。
如何使一些 dc
图表具有方向性。是通过一些禁用鼠标输入的技巧吗?
主要问题
与host
相反,foo
和bar
是non-exclusive。每个交易的主机要么是某物,要么是另一个,但交易的 header 可能包括 foo
和 bar
.
如何为 requestHeaders
定义交叉过滤器尺寸,然后如何使用 dc
?即
var ndx = crossfilter(data);
...
var requestHeadersDim = ndx.dimension(function(d) {
// What should go here?
});
通过查看 dc
的源代码破解了它(高效但非常不优雅)。可以扭曲 crossfilter
的含义来达到预期的效果。
最后的结果就在这个fiddle。它比问题稍微有限,因为 responseHeaders
的字段被硬编码为 foo
、bar
和 baz
。删除此限制更多是在简单 Javascript.
小问题
使用simple css hack,我简单定义了
.avoid-clicks {
pointer-events: none;
}
并给了 div 这个 class。不优雅但有效。
主要问题
主要问题是通过扭曲crossfilter
概念的意义来解决的,"fooling"dc
。
假设数据如下所示:
var transactions = [
{
"time": 0,
"host": "a.com",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 0},
"numBytes": 12
},
{
"time": 1,
"host": "b.org",
"requestHeaders": {"foo": 0, "bar": 1, "baz": 1},
"responseHeaders": {"shmip": 0, "shmap": 1, "shmoop": 1},
"numBytes": 3
},
...
];
我们可以定义一个"dummy"维度,忽略数据:
var transactionsNdx = crossfilter(transactions);
var dummyDim = transactionsNdx
.dimension(function(d) {
return 0;
});
使用这个维度,我们可以定义一个组来计算筛选行的总 foo
、bar
和 baz
字节:
var requestHeadersGroup = dummyDim
.group()
.reduce(
/* callback for when data is added to the current filter results */
function (p, v) {
return {
"foo": p.foo + v.requestHeaders.foo * v.numBytes,
"bar": p.bar + v.requestHeaders.bar * v.numBytes,
"baz": p.baz + v.requestHeaders.baz * v.numBytes,
}
},
/* callback for when data is removed from the current filter results */
function (p, v) {
return {
"foo": p.foo - v.requestHeaders.foo * v.numBytes,
"bar": p.bar - v.requestHeaders.bar * v.numBytes,
"baz": p.baz - v.requestHeaders.baz * v.numBytes,
}
},
/* initialize p */
function () {
return {
"foo": 0,
"bar": 0,
"baz": 0
}
}
);
请注意,这根本不是一个合适的 crossfilter
组。它不会将维度映射到它们的值。相反,它将 0 映射到一个值,该值本身将维度映射到它们的值(丑陋!)。因此,我们需要将这个组转换成实际上看起来像 crossfilter
组的东西:
var getSortedFromGroup = function() {
var all = requestHeadersGroup.all()[0].value;
all = [
{
"key": "foo",
"value": all.foo
},
{
"key": "bar",
"value": all.bar
},
{
"key": "foo",
"value": all.baz
}];
return all.sort(function(lhs, rhs) {
return lhs.value - rhs.value;
});
}
var requestHeadersDisplayGroup = {
"top": function(k) {
return getSortedFromGroup();
},
"all": function() {
return getSortedFromGroup();
},
};
我们现在可以创建常规 dc
图表,并传递适配器组
requestHeadersDisplayGroup
去吧。从此时开始它正常工作。
我通常处理您陈述的主要问题的方法是转换我的数据,以便每个 header 都有一个单独的记录(这些重复记录中的所有其他字段都是相同的)。然后我使用自定义组聚合来避免 double-counting。这些自定义聚合有点难以管理,所以我使用 'exception' 函数构建了 Reductionio 来帮助解决这个问题 - github.com/esjewett/reductio