NVD3 离散条形图上的钟形曲线/正态分布曲线

Bell Curve / Normal Disribution Curve On A NVD3 Discrete Bar Chart

我正在尝试找出一种将分布曲线/钟形曲线绘制到 NVD3 图表上的方法。我在网上搜索了很多,发现几乎没有什么可以与我所拥有的一起工作。也许这实际上是不可能的,但我认为这值得一问,也很高兴知道其他任何会寻找类似东西的人。

这是我需要的图形示例(在 google 图片上找到)

从示例中可以看出,直线不需要第二个轴,因此不需要 'bar and line chart combo'。我知道您可以使用 D3 直接在 canvas 上绘图,但我对此经验不足。

这是我的代码,jsfiddle如果有人想看

var json = [{ "values": [{"label":"450-456", "value":0, "color":"#D62728"},{"label":"456-462", "value":0, "color":"#D62728"},{"label":"462-468", "value":0, "color":"#D62728"},{"label":"468-474", "value":0, "color":"#D62728"},{"label":"474-480", "value":0, "color":"#D62728"},{"label":"480-486", "value":1, "color":"#D62728"},{"label":"486-492", "value":5, "color":"#D62728"},{"label":"492-498", "value":3, "color":"#D62728"},{"label":"498-504", "value":5, "color":"#D62728"},{"label":"504-510", "value":6, "color":"#D62728"},{"label":"510-516", "value":9, "color":"#D62728"},{"label":"516-522", "value":6, "color":"#D62728"},{"label":"522-528", "value":1, "color":"#D62728"},{"label":"528-534", "value":0, "color":"#D62728"},{"label":"534-540", "value":0, "color":"#D62728"},{"label":"540-546", "value":0, "color":"#D62728"},{"label":"546-552", "value":0, "color":"#D62728"},{"label":"552-558", "value":0, "color":"#D62728"},{"label":"558-564", "value":0, "color":"#D62728"},{"label":"564-570", "value":0, "color":"#D62728"}]}];




                nv.addGraph(function() {
                var chart = nv.models.discreteBarChart()
                .x(function(d) {
                return d.label
                })
                .y(function(d) {
                return d.value
                })  
                .staggerLabels(true)

                .tooltips(true)
                .showValues(true)
                .transitionDuration(250)
                ;

                chart.yAxis
                .tickFormat(d3.format('.0f'))
                chart.valueFormat(d3.format('d'));
               // REMOVE DECIMAL PLACES FROM Y AXIS
                chart.forceY([0,10]);

                d3.select('#chartDisribution svg')
                .datum(json)
                .call(chart);

                d3.select('#chartDisribution svg')
                .append("text")
                .attr("x", '50%')             
                .attr("y", 10)
                .attr("text-anchor", "middle")
                .style("font-size", "14px") 
                .style("text-decoration", "underline")
                .style("font-weight", "bold")
                .style("height", "20px")     
                .text("DISRIBUTION");

                nv.utils.windowResize(chart.update);
                return chart;
                });    

分发前的原始数据 -

[518, 514, 512, 514, 518, 498, 510, 516, 520, 508, 504, 504, 517, 494, 492, 491, 515, 507, 492, 527, 509, 500, 491, 506, 517, 516, 518, 505, 514, 486, 516, 504, 503, 490, 515, 498]

如果需要更多信息,请询问。

谢谢

如@Altocumulus 所述,您可以使用 LinePlusBarChart。

有很多关于如何执行此操作的信息,因此我将仅解释如何为正态分布生成数据。

以下公式用于创建数据:Wikipedia Source

所以我们需要的是总数据集的标准差和平均值以及您用于直方图的 bin。

我不会详细介绍如何根据您的数据集计算平均值和标准偏差,但执行此操作的代码包含在下面的 fiddle 中。

我们首先声明数据集和 bins:

var values = [518, 514, 512, 514, 518, 498, 510, 516, 520, 508, 504, 504, 517, 494, 492, 491, 515, 507, 492, 527, 509, 500, 491, 506, 517, 516, 518, 505, 514, 486, 516, 504, 503, 490, 515, 498];

var bins=[450, 456, 462, 468, 474, 480, 486, 492, 498, 504, 510, 516, 522, 528, 534, 540, 546, 552, 558, 564]

该数据集的均值和标准差如下:

var average = 507.1944444
var std = 10.43022927

根据这些数据,我们可以计算出公式的第一部分:

var ni1 = 1 / (std * Math.sqrt(2 * Math.PI));

公式的第二部分使用 bin,因此我们循环遍历每个 bin 以计算正态曲线的值。

为了将正常值缩放到图表中,我们需要每个 bin 之间的大小以及值的总数。

(我还添加了一个名为 norm 的变量,但我们仅使用它来将结果输出到屏幕)

var norm ="norm data"
var length = bins.length;
var bin_distance = 6;
var num_records = 36;

for(var i=0;i<length;i++){
    // This is the second part of the formula 
    var ni2 = Math.exp(-1*((bins[i]-average)*(bins[i]-average))/(2* (std*std))) 

    // this is the final calculation for the norm values. I also rounded the value but thats up to you if you want, you can remove this for unrounded values.   
    var normdata = Math.round(ni1*ni2*bin_distance*num_records);

    //append value to norm to output to screen
    norm = norm +"<p>"+ bins[i]+" - "+normdata+"</p>"
}

//output results to screen: 
document.getElementById('chartDisribution').innerHTML = norm;   

这里是working fiddle.

对于您的图表,您可能希望将 normdata 值推送到您为您的线声明的对象中。