我想在我的仪表板上添加一个损耗率%图表,但是我很难弄清楚如何使用复杂的计算来做到这一点。
基本上,损耗率%需要回顾前12个时期 - 每个时期。
例如,如果期间是201710 [YYYYMM],那么计算将是:
(201611至201710期间的总发起人数)/ 201610期间的负责人+ 201611至2017年期间的总离职人数
在折线图中,您对每个时段都有相同的计算方法。
所以,如果我有以下数据:
{ ... }
{ "Period": 201601, "Heads": 100, "Starters": 10, "Leavers": 8 },
{ "Period": 201602, "Heads": 102, "Starters": 8, "Leavers": 8 },
{ "Period": 201603, "Heads": 102, "Starters": 3, "Leavers": 0 },
{ "Period": 201604, "Heads": 105, "Starters": 8, "Leavers": 12 },
{ "Period": 201605, "Heads": 101, "Starters": 2, "Leavers": 5 },
{ "Period": 201606, "Heads": 98, "Starters": 8, "Leavers": 11 },
{ "Period": 201607, "Heads": 101, "Starters": 6, "Leavers": 5 },
{ "Period": 201608, "Heads": 102, "Starters": 4, "Leavers": 1 },
{ "Period": 201609, "Heads": 105, "Starters": 11, "Leavers": 17 },
{ "Period": 201610, "Heads": 99, "Starters": 8, "Leavers": 11 },
{ "Period": 201611, "Heads": 96, "Starters": 5, "Leavers": 8 },
{ "Period": 201612, "Heads": 95, "Starters": 4, "Leavers": 5 },
{ "Period": 201701, "Heads": 91, "Starters": 1, "Leavers": 5 },
201701期的计算和损耗率%为:
初学者(201602-201701期): 68 /(负责人(201601期): 100 +离校者(期间201602-201701):88
201701年的流失率为:36.17%
我还希望有一个数字显示,显示最近一段时间的流失率。
我有一些示例数据和期间图表可以在jsfiddle中使用:https://jsfiddle.net/kevinelphick/nh34aknn/
这个组的自定义缩小功能如下:
attritionGroup = dimPeriod.group().reduce(
function (p, d) {
p.heads += d.Heads;
p.starters += d.Starters;
p.leavers += d.Leavers;
return p;
},
function (p, d) {
p.heads -= d.Heads;
p.starters -= d.Starters;
p.leavers -= d.Leavers;
return p;
},
function () {
return {heads: 0, starters: 0, leavers: 0};
});
我很欣赏这可能是一个很长的镜头,因为它的复杂性,我希望我没有混淆地描述我的问题。我过去曾尝试过,但由于我的知识有限,我找不到任何可行的解决方案。我只能猜测它必须动态地遍历数组以总结启动器,我需要的所需周期的离开器?我是否需要计算一个独特的周期来计算我计算所需的正确周期?
答案 0 :(得分:2)
reduce会为您设置组,然后您可以使用计算损耗率的虚拟组。
(更新代码)
function calcAttritionGroup (group) {
return {
all() {
var groupAll = group.all()
groupAll.forEach((p) => {
let elevenMonthsAgo = d3.time.month.offset(p.key, -11)
let twelveMonthsAgo = d3.time.month.offset(p.key, -12)
let twelveMonthsAgoGroup = groupAll.find(function(g){
return g.key.getTime() === twelveMonthsAgo.getTime()
})
let attrHeads = null
if (twelveMonthsAgoGroup) {
attrHeads = twelveMonthsAgoGroup.value.heads;
}
p.attrition = null
if (attrHeads) {
let subgroup = groupAll.filter(function(g) {
return g.key <= p.key && g.key >= elevenMonthsAgo;
})
let attrStarters = subgroup.reduce(function(sum, n) {
return sum + n.value.starters
}, 0)
let attrLeavers = subgroup.reduce(function(sum, n) {
return sum + n.value.leavers
}, 0)
let attrRate = (attrStarters / (attrHeads + attrLeavers))
p.attrition = attrRate || null
})
return groupAll
}
};
}
以下是对小提琴的修改:https://jsfiddle.net/ga7x1p8m/(更新) (注意,问题中的值和公式与小提琴中的不同。)
有些观点......
1 - 将这段时间格式化并不会让你走得太远,因为它不会为你的x刻度提供一个平滑的范围,并且很难进行你需要获得的比较以前的时期。最简单的可能是作为日期对象进行投射。
var format = d3.time.format("%Y%m");
data.forEach(function (d) {
d.date = format.parse(d.Period + '')
})
2 - 您必须管理边缘案例。如果找不到上个12个月的时间会怎样?如果使用了最早的可用时段,那么这将为计算添加更多逻辑。