使用dc.js和crossfilter制作一个显示人口衰减的线图

时间:2016-02-28 21:49:21

标签: data-visualization dc.js crossfilter

我正在DC.js中创建一个仪表板。其中一个可视化是生存曲线,显示y轴上的存活百分比和x轴上的周数时间

数据集中的每条记录都包含一个名为recidiefNa的deathAfter列。这显示死亡发生后的周数,并显示存活率为-99。

请参阅草图,例如数据集和所需的图表形式: sketch of desired outcome

我创建了此代码来创建尺寸和组并绘制所需的图表。

var recDim = cf1.dimension(dc.pluck('recidiefNa'));//sets dimension
            var recGroup = recDim.group().reduceCount();

            var resDim = cf1.dimension(dc.pluck('residuNa'));
            var resGroup = resDim.group().reduceCount();



            var scChart = dc.compositeChart("#scStepChart");
            scChart
            .width(600)
            .height(400)
            .x(d3.scale.linear().domain([0,52]))
            .y(d3.scale.linear().domain([0,100]))
            .clipPadding(10)
            .brushOn(false)
            .xAxisLabel("tijd in weken")
            .yAxisLabel("percentage vrij van residu/recidief")
            .compose([
                dc.lineChart(scChart)
                    .dimension(recDim)
                    .group(recGroup)
                    .interpolate("step-after")
                    .renderDataPoints(true)
                    .renderTitle(true)
                    .keyAccessor(function(d){return d.key;})
                    .valueAccessor(function(d){return (d.value/cf1.groupAll().reduceCount().value()*100);}),
                dc.lineChart(scChart)
                    .dimension(resDim)
                    .group(resGroup)
                    .interpolate("step-after")
                    .renderDataPoints(true)
                    .colors(['orange'])
                    .renderTitle(true)
                    .keyAccessor(function(d){return d.key;})
                    .valueAccessor(function(d){return (d.value/cf1.groupAll().reduceCount().value()*100 );})
            ])                    
            .xAxis().ticks(4);
            scChart.render();

这给出了以下结果:

first attempt

正如你所看到的,我的第一个问题是我需要延长线直到y轴显示x = 0weeks和y = 100%作为第一个数据点。

这就是第一个问题:有没有办法让这条线看起来更像我的草图(从y轴开始是100%?

我的第二个和更大的问题是它显示了我需要的百分比的倒数(例如38而不是62)。这是因为数据的结构方式(这有点儿而不是改变)

首先我尝试将valueaccessor更改为100- *计算出的数字。这显然是解决这个问题的常用方法。但是我的结果是:

with value accessor

正如您现在所看到的,生存曲线是一个积极的倾斜,这在生存曲线中是不可能的。这是我的第二个问题。任何想法如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

啊,从特定的例子中不清楚每个数据点应该基于最后一个,但你的评论清楚地表明了这一点。听起来你正在寻找的是一种累积总和 - 在你的情况下,累积减法。

There is an entry in the FAQ for this.

使该代码适应您的用例:

function accumulate_subtract_from_100_group(source_group) {
    return {
        all:function () {
            var cumulate = 100;
            return source_group.all().map(function(d) {
                cumulate -= d.value;
                return {key:d.key, value:cumulate};
            });
        }
    };
}

像这样使用:

var decayRecGroup = accumulate_subtract_from_100_group(recGroup)
   // ...
      dc.lineChart(scChart)
         // ...
            .group(decayRecGroup)

,同样适用于resGroup

在我们处理此问题时,我们可以将数据连接到初始点,以回答您的第一个问题:

function accumulate_subtract_from_100_and_prepend_start_point_group(source_group) {
    return {
        all:function () {
            var cumulate = 100;
            return [{key: 0, value: cumulate}]
               .concat(source_group.all().map(function(d) {
                  cumulate -= d.value;
                  return {key:d.key, value:cumulate};
               }));
        }
    };
}

(只有博览会的荒谬功能名称!)

编辑:这是@ Erik的内置百分比转换的最终改编答案,以及一些性能改进:

function fakeGrouper(source_group) {
    var groupAll = cf1.groupAll().reduceCount();
    return {
        all:function () {
            var cumulate = 100;
            var total = groupAll.value();
            return [{key: 0, value: cumulate}]
                .concat(source_group.all().map(function(d) {
                    if(d.key > 0) {             
                        cumulate -= (d.value/total*100).toFixed(0);
                    }
                    return {key:d.key, value:cumulate};
                }));
        }
    };
}