dc.js 绘制嵌套数据数组的图表
dc.js charting nested data arrays
问题描述
我有一个结构类似于以下内容的大型数据数组,我想创建一个图表来按创建变更集的时间显示时间记录的变更集。
[ // array of records
{
id: 1,
name: 'some record',
in_datetime: '2019-10-24T08:15:00.000000',
out_datetime: '2019-10-24T10:15:00.000000',
hours: 2,
tasks: ["some task name", "another task"],
changesets: [ //array of changesets within a record
{
id: 1001,
created_at: '2019-10-24T09:37:00.000000'
},
...
]
},
...
]
无论我如何尝试创建 dimension/write 缩减函数,我都无法从数据 table.
中获取正确的值
const changeReduceAdd = (p, v) => {
v.changesets.forEach(change => {
let cHour = timeBand[change.created_hour]
if (showByChanges) {
p[cHour] = (p[cHour] || 0) + (change.num_changes || 0)
} else {
p[cHour] = (p[cHour] || 0) + 1 //this is 1 changeset
}
})
return p
}
const changeReduceRemove = (p, v) => {
v.changesets.forEach(change => {
let cHour = timeBand[change.created_hour]
if (showByChanges) {
p[cHour] = (p[cHour] || 0) - (change.num_changes || 0)
} else {
p[cHour] = (p[cHour] || 0) - 1 //this is 1 changeset
}
})
return p
}
const changeReduceInit = () => {
return {}
}
//next create the array dimension of changesets by hour
//goal: show changesets or num_changes grouped by their created_hour
let changeDim = ndx.dimension(r => r.changesets.map(c => timeBand[c.created_hour]), true)
let changeGroup = changeDim.group().reduce(changeReduceAdd, changeReduceRemove, changeReduceInit)
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension(changeDim)
.keyAccessor(d => d.key)
.valueAccessor(d => d.value[d.key])
.group(changeGroup)
我遇到的主要问题是我想要 changesets/created_hour 图表,但在我尝试过的每个维度中,键显示正确的地方,值都明显高于预期。
“8AM”类别中的值为 5,而实际上只有 3 个我标记的变更集 created_hour: 8
:
"tag dimension"问题有很多解法,你恰好选择了其中最好的两个。
两者都
- 自定义减少,或
- 维度构造函数的 array/tag 标志参数
就可以了。
将这两种技术结合起来会给您带来麻烦。我没有试图弄清楚到底发生了什么,但你以某种方式总结了小时数。
简单的解决方案:使用内置标签维度功能
使用 tag/dimension 标志和默认值 reduceCount
:
let changeDim = ndx.dimension(r => r.changesets.map(c => timeBand[c.created_hour]), true)
let changeGroup = changeDim.group(); // no reduce, defaults to reduceCount
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension(changeDim)
.keyAccessor(d => d.key)
.valueAccessor(d => d.value) // no [d.key], value is count
.group(changeGroup)
手册,1.4 之前的组所有版本
您的代码中还有一个 groupAll 解决方案。在 crossfilter 1.4 中引入 array/tag 维度之前,此解决方案是必需的。
出于好奇,我尝试启用它,一旦您将 groupAll 结果转换为组结果,它也可以工作:
function groupall_map_to_group(groupall) {
return {
all: () => Object.entries(groupall.value())
.map(([key,value])=>({key,value}))
}
}
let changeGroup = ndx.groupAll().reduce(changeReduceAdd, changeReduceRemove, changeReduceInit)
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension({}) // filtering not implemented
.keyAccessor(d => d.key)
.valueAccessor(d => d.value) // [d.key]
.group(groupall_map_to_group(changeGroup))
.x(dc.d3.scaleBand().domain(timeBand))
.xUnits(dc.units.ordinal)
.elasticY(true)
.render()
问题描述
我有一个结构类似于以下内容的大型数据数组,我想创建一个图表来按创建变更集的时间显示时间记录的变更集。
[ // array of records
{
id: 1,
name: 'some record',
in_datetime: '2019-10-24T08:15:00.000000',
out_datetime: '2019-10-24T10:15:00.000000',
hours: 2,
tasks: ["some task name", "another task"],
changesets: [ //array of changesets within a record
{
id: 1001,
created_at: '2019-10-24T09:37:00.000000'
},
...
]
},
...
]
无论我如何尝试创建 dimension/write 缩减函数,我都无法从数据 table.
中获取正确的值const changeReduceAdd = (p, v) => {
v.changesets.forEach(change => {
let cHour = timeBand[change.created_hour]
if (showByChanges) {
p[cHour] = (p[cHour] || 0) + (change.num_changes || 0)
} else {
p[cHour] = (p[cHour] || 0) + 1 //this is 1 changeset
}
})
return p
}
const changeReduceRemove = (p, v) => {
v.changesets.forEach(change => {
let cHour = timeBand[change.created_hour]
if (showByChanges) {
p[cHour] = (p[cHour] || 0) - (change.num_changes || 0)
} else {
p[cHour] = (p[cHour] || 0) - 1 //this is 1 changeset
}
})
return p
}
const changeReduceInit = () => {
return {}
}
//next create the array dimension of changesets by hour
//goal: show changesets or num_changes grouped by their created_hour
let changeDim = ndx.dimension(r => r.changesets.map(c => timeBand[c.created_hour]), true)
let changeGroup = changeDim.group().reduce(changeReduceAdd, changeReduceRemove, changeReduceInit)
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension(changeDim)
.keyAccessor(d => d.key)
.valueAccessor(d => d.value[d.key])
.group(changeGroup)
我遇到的主要问题是我想要 changesets/created_hour 图表,但在我尝试过的每个维度中,键显示正确的地方,值都明显高于预期。
“8AM”类别中的值为 5,而实际上只有 3 个我标记的变更集 created_hour: 8
:
"tag dimension"问题有很多解法,你恰好选择了其中最好的两个。
两者都
- 自定义减少,或
- 维度构造函数的 array/tag 标志参数
就可以了。
将这两种技术结合起来会给您带来麻烦。我没有试图弄清楚到底发生了什么,但你以某种方式总结了小时数。
简单的解决方案:使用内置标签维度功能
使用 tag/dimension 标志和默认值 reduceCount
:
let changeDim = ndx.dimension(r => r.changesets.map(c => timeBand[c.created_hour]), true)
let changeGroup = changeDim.group(); // no reduce, defaults to reduceCount
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension(changeDim)
.keyAccessor(d => d.key)
.valueAccessor(d => d.value) // no [d.key], value is count
.group(changeGroup)
手册,1.4 之前的组所有版本
您的代码中还有一个 groupAll 解决方案。在 crossfilter 1.4 中引入 array/tag 维度之前,此解决方案是必需的。
出于好奇,我尝试启用它,一旦您将 groupAll 结果转换为组结果,它也可以工作:
function groupall_map_to_group(groupall) {
return {
all: () => Object.entries(groupall.value())
.map(([key,value])=>({key,value}))
}
}
let changeGroup = ndx.groupAll().reduce(changeReduceAdd, changeReduceRemove, changeReduceInit)
let changeChart = dc.barChart('#changeset-hour-chart')
.dimension({}) // filtering not implemented
.keyAccessor(d => d.key)
.valueAccessor(d => d.value) // [d.key]
.group(groupall_map_to_group(changeGroup))
.x(dc.d3.scaleBand().domain(timeBand))
.xUnits(dc.units.ordinal)
.elasticY(true)
.render()