我正在使用dc.js创建具有“变更集”数组的可交叉过滤的图表,这些变更集具有如下所示的架构:
id,
first_name, last_name, user_id,
created_at,
num_changes,
hashtags: [str],
total_add, total_mod, total_del,
buildings_add, buildings_mod, buildings_del,
pois_add, pois_mod, pois_del,
roads_add, roads_mod, roads_del,
road_km_add, road_km_mod, road_km_del,
waterways_add, waterways_mod, waterways_del,
waterway_km_add, waterway_km_mod, waterway_km_del
}
我试图创建可过滤的堆叠条形图,其中的条形图表示add/mod/del
,堆栈表示变化的数据类型buildings/pois/roads/waterways/road_km/waterway_km
。
任何1个变更集可以具有这些字段的任意组合,因此不能将每个变更集与1个修改类型配对。有没有更好的方法可以完成此分组,可以在图表上应用过滤器了?
我可以使用正确的数据显示图表,但是我设置它的方式已经做到了,因此无法过滤图表。最初,我将维写为crossfilter.dimension(d => ['add', 'mod', 'del'], true)
,以便每个变更集都显示在每个bin中。但是由于所有变更集都将共享add / mod / del,因此不会过滤任何内容。
然后我在这里看到了过滤器堆栈示例:https://github.com/dc-js/dc.js/blob/develop/web-src/examples/filter-stacks.html
然后我尝试为编辑运行多键维度
let editDim = ndx.dimension(d => {
let rt = []
stackKeys.forEach(key => {
editStacks.forEach(stack => {
if (d[sAcc(stack,key)]) {
rt.push(key + '.' + stack)
}
})
})
return rt
}, true)
此方法看起来非常接近,但过滤堆栈不会在其他图表上产生正确的结果。 似乎无论我选择从该图表中过滤掉什么,其他图表都会产生0。
这是一个jsfiddle,其中我有1个使用多键方法的堆叠条形图,1个使用['add','mod','del']键方法的堆叠条形图和1个常规条形图图表以比较结果/进行过滤。
为了将变更集分为几组,我使用了一个自定义的reducer,它将数据转换为类似的内容
{
key: 'add',
value: {
add: {
buildings': 42,
pois: 12,
roads: 1,
waterway: 2,
waterway_km: 0.003,
road_km: 0
},
mod: {...}
del: {...}
}
}
该维度分组为['add', 'mod', 'del']
,并使用
const editStacks = ['buildings', 'pois', 'roads', 'waterways']
editStacks.forEach((stack, i) => {
// first is group, others are stacked
let action = i ? 'stack' : 'group'
chart[action](group, stack, d => d.value[d.key][stack])
})
在多键方法中,将值转换为正
{key: 'add', value: {building, roads, pois, waterways}}
使用此功能
all: function () {
var all = group.all()
var m = {}
all.forEach(kv => {
let [k,s] = kv.key.split('.')
m[k] = m[k] || {}
m[k][s] = kv.value[k][s]
})
return Object.keys(m).map(key => {
return {key, value: m[key]}
})
}
答案 0 :(得分:0)
因此,要使堆积的条块可按每个部分进行过滤,我必须结合使用以下内容中的答案 dc.js - Creating a row chart from multiple columns and enabling filtering 和在 Plotting aggregated data with sub-columns in dc.js
要构建可过滤的维度,您必须使用第一个链接中描述的方法在维度上创建自定义的filterHandler,该维度仅按元素分组
let dimension = ndx.dimension(d => d)
然后我通过使用groupAll并创建一个对象来构造我的组
{ key.stack: value }}
使用reduce函数。
然后,我通过为该组创建“全部”方法将其转换回标准组
如第二个链接所述。
function reduceAdd (p, v) {
keys.forEach(k => {
stacks.forEach(s => {
p[`${k}.${s}`] += v[accessor(k, s)] || 0
})
})
return p
}
function reduceRemove (p, v) {
keys.forEach(k => {
stacks.forEach(s => {
p[`${k}.${s}`] -= v[accessor(k, s)] || 0
})
})
return p
}
function reduceInit () {
let p = {}
keys.forEach(k => {
stacks.forEach(s => {
p[`${k}.${s}`] = 0
})
})
return p
}
function stackedGroup (group) {
return {
all: function () {
var all = Object.entries(group.value()).map(([key, value]) => ({ key, value }))
var m = {}
all.forEach(kv => {
let [k, s] = kv.key.split('.')
m[k] = m[k] || {}
m[k][s] = kv.value
})
return Object.keys(m).map(key => {
return { key, value: m[key] }
})
}
}
}
let group = dimension.groupAll().reduce(reduceAdd, reduceRemove, reduceInit)
group = stackedGroup(group)
最后,您必须按照第一个链接中所述重新定义过滤器处理程序。这个过滤器是我用来过滤的 “具有至少1个x的变更集”,其中“ x”是某种类型的编辑,例如“添加建筑物”或“修改后的道路”
chart.filterHandler((dim, filters) => {
if (filters && filters.length) {
dim.filterFunction((r) => {
return filters.some((c) => {
//the changeset must have a value in this field to be left in the chart
let [stack, field] = c[0].split('.')
return r[accessor(field, stack)] > 0
})
})
} else {
dim.filter(null)
}
return filters
})
此后,主题标签图表显示了意外的结果,因此我也必须对主题标签图表进行类似的标注和分组。
我相信这是因为主题标签图表是使用数组维度定义的,但是将其分组为d => d
并定义自定义filterHandler产生了令我满意的结果。
可以对两个图表进行过滤,以找到问题的结果,例如“有#Kaart主题标签的变更集有多少条道路经过修改”。
再次感谢@戈登!