无法使用D3.js和Angular7设置概率直方图的bin的正确高度

时间:2019-06-06 10:02:37

标签: javascript angular d3.js histogram

我正在尝试使用d3v4和角度7构建简单的概率直方图,但是由于某些原因,我无法正确计算每个垃圾箱的高度。相反,当我运行代码时,我得到的所有垃圾箱的高度都很大,超出了预期的比例。

这是我正在使用的代码。

private buildChart() {
this.chartProps = {};
let _this = this;

// Number of bins for the histogram
let numHistBins = 10; 

// If true, the number of bins are calculated automatically and numHistBins is overwritten
let calcHistBinsAutmoatic = true; 

// calculate the number of histogram bins
if (calcHistBinsAutmoatic) {
  numHistBins = Math.ceil(Math.sqrt(this.plotData.length));
}

// Bandwith (smoothing constant) h of the kernel density estimator
let bandwith = 1.06 * this.standardDeviation(this.plotData) * Math.pow(this.plotData.length, - 1 / 5); 

// Set the dimensions of the canvas / graph
let margin = {top: 20, right: 30, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 350 - margin.top - margin.bottom;

// Calculate the range of the b_values
let dist = d3.max(this.plotData) - d3.min(this.plotData);

// Define the bins function
let bins = d3.histogram().thresholds(numHistBins);

// Get the total number of elements ( used because of the probability histogram )
this.chartProps.totalData = this.plotData.length;

// Define the X/Y scales
this.chartProps.x = d3.scaleLinear()
.range([0, width])
.domain([d3.min(this.plotData) - (dist / 2), d3.max(this.plotData) + (dist / 2)]);

this.chartProps.y = d3.scaleLinear()
.range([height, 0])
.domain([0, d3.max(bins(this.plotData), function (d) {
  return d.length/_this.chartProps.totalData;
}) + 0.1]);

this.chartProps.yForHistogram = d3.scaleLinear()
.domain([0, d3.max(bins(this.plotData), function(d) {
  return d.length/_this.chartProps.totalData;
})])
.range([height, 0]);

// Define the axes
var xAxis = d3.axisBottom(this.chartProps.x);
var yAxis = d3.axisLeft(this.chartProps.y);

// Calculate Kernel Density Estimator
var kde = this.kernelDensityEstimator(this.gaussianKernel(bandwith), this.chartProps.x.ticks(100));

// Define the line function (Used if KDE is true)
var line = d3.line<any>()
.x( d => { return _this.chartProps.x(d[0]); })
.y( d => { return _this.chartProps.y(d[1]); });

// Prepare the SVG
var svg = d3.select(this.chartElement.nativeElement)
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);

// Add the X Axis
svg.append('g')
.attr('class', 'x axis')
.attr('transform', `translate(0,${height})`)
.call(xAxis)
.append("text")
.attr("class", "label")
.attr("x", width)
.attr("y", -6)
.style("text-anchor", "end")
.text("Value");

// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);

// Add the bars of histogram
svg.selectAll(".bar")
.data(bins(_this.plotData))
.enter().insert("rect", ".axis")
.attr("class", "bar")
.attr("fill", "#bbb")
.attr("x", d => {
  return this.chartProps.x(d.x0) + 1;
})
.attr("y", d => this.chartProps.y(d.length))
.attr("width", d => Math.max(0, this.chartProps.x(d.x1) - this.chartProps.x(d.x0) - 1))
.attr("height", d => {
   return this.chartProps.yForHistogram(0) - this.chartProps.yForHistogram(d.length)
});



if (_this.showKDP == true) {
  // console.log(kde(_this.plotData));
  svg.append("path")
  .datum(kde(_this.plotData))
  .attr("class", "line")
  .attr("stroke", "red")
  .attr("fill", "none")
  .attr("d", line);
}

...
}

这也是图形的外观

enter image description here

任何关于我在这里做错事情的想法都会受到欢迎。

0 个答案:

没有答案