我正在使用react-chartjs-2中的散点图开发一个react应用程序。我创建了一些帮助函数来计算并在图表上绘制95%置信区间椭圆。到目前为止,一切顺利。
它大部分工作得很好(至少从视觉的Angular 来看),但有时,我得到一些奇怪的结果-以下面的蓝色项目为例。旋转似乎关闭,因为你可以把所有的蓝色项目放进一个稍微小一点的,但旋转的椭圆中。
我已经把下面的代码,并很高兴提供更多的信息,如果任何人都可以帮助:
1.解释为什么这个结果有意义或
1.帮助我找出如何调整我的方法,以获得更好的结果。
谢谢!
const calculateEllipse = (points, xAxis, yAxis) => {
const n = points.length;
const xMean = points.reduce((sum, p) => sum + p.x, 0) / n;
const yMean = points.reduce((sum, p) => sum + p.y, 0) / n;
let a = 0;
let b = 0;
let c = 0;
points.forEach((p) => {
const xPixel = xAxis.getPixelForValue(p.x) - xAxis.getPixelForValue(xMean);
const yPixel = yAxis.getPixelForValue(p.y) - yAxis.getPixelForValue(yMean);
a += xPixel * xPixel;
b += xPixel * yPixel;
c += yPixel * yPixel;
});
a /= n;
b /= n;
c /= n;
const d = Math.sqrt((a - c) * (a - c) + 4 * b * b);
const e1 = (a + c + d) / 2;
const e2 = (a + c - d) / 2;
const angle = (a > c ? Math.atan2(b, a - e1) : Math.atan2(c - e1, b)) / 2;
const scaleFactor = 2.4477; // Scaling factor for a 95% confidence ellipse
return {
x: xAxis.getPixelForValue(xMean),
y: yAxis.getPixelForValue(yMean),
a: Math.sqrt(e1) * scaleFactor,
b: Math.sqrt(e2) * scaleFactor,
angle,
};
};
const ellipsePlugin = {
id: "ellipse",
afterDatasetsDraw: function (chart, args, options) {
const ctx = chart.ctx;
const show = chart.options.plugins.ellipse.show;
const chartArea = chart.chartArea; // get the chart area
const xAxis = chart.scales.x;
const yAxis = chart.scales.y;
if (show) {
chart.data.datasets.forEach((dataset, index) => {
if (chart.isDatasetVisible(index)) {
const ellipseData = calculateEllipse(dataset.data, xAxis, yAxis);
ctx.save();
// check if any part of the ellipse is outside the chart area
if (
ellipseData.x - ellipseData.a <= chartArea.right &&
ellipseData.x + ellipseData.a >= chartArea.left &&
ellipseData.y - ellipseData.b <= chartArea.bottom &&
ellipseData.y + ellipseData.b >= chartArea.top
) {
// draw only if the ellipse is completely inside the chart area
ctx.beginPath();
ctx.translate(ellipseData.x, ellipseData.y);
ctx.rotate(ellipseData.angle);
ctx.scale(ellipseData.a, ellipseData.b);
ctx.arc(0, 0, 1, 0, 2 * Math.PI);
ctx.restore();
ctx.strokeStyle = dataset.borderColor;
ctx.lineWidth = 2;
ctx.stroke();
}
}
});
}
},
};
1条答案
按热度按时间m528fe3b1#
我觉得你的Angular 公式不对,肯定有原因,我没有按照计算,但我验证了standard formula(式(23)):
工作正常-请参见下面的模拟。
atan2
的使用使得公式对a〉c和a〈c都有效。x一个一个一个一个x一个一个二个x