javascript - 在d3中获取大部分点集中在2D图表上的中心
问题描述
我有一张2D
图表,其中点形成集群。我需要一种为这些集群设置标签的方法,所以我需要集群中大多数点集中的坐标。不幸的是,我不能使用getBoundingBoxCenter
,因为有些点位于主集群之外。这是我现在所拥有的:
createClusterLabels = () => {
if (this.props.mainData && this.props.mainData.length || this.props.type === "main") {
var numClust = this.props.type === "marker" ? this.props.mainData.length : this.props.datum.length;
var that = this;
var groups = d3.select("svg > .nv-scatterChart").selectAll(".nv-groups > .nv-group");
groups.each(function(data, idx) {
let key = data["key"];
let g = d3.select(this);
let parent = d3.select(this.parentNode);
let center = that.getBoundingBoxCenter(g);
let margin = key.length === 1 ? 3 : 7;
let old_key = parent.selectAll("text")
.filter(function(textData) {
let text = d3.select(this).text();
if (text === key) {
return true;
}
return false;
});
// If we are adding the nodes the first time, they should be 'nulls' in current html
let size = old_key.size();
if (size === 0 && key <= numClust) {
parent.append("circle")
.attr("cx", center[0])
.attr("cy", center[1])
.attr("r", 10)
.attr('fill-opacity', 0)
.style("stroke", "black");
parent.append("text")
.attr("x", center[0] - margin)
.attr("y", center[1])
.attr("dy", ".35em")
.style("font-weight", "bold")
.style("fill", "black")
.text(key);
}
});
}
}
现在center
是不精确的。该图表如下所示:
我需要一种方法来排除位于它们主要集中点之外的某些点。是否可以在javascript中实现?
解决方案
我能够确定每个集群内每个单点的位置,然后排除在x
or上高于 1 个标准差的y
点,然后使用剩余的点,只使用平均值。这是我所做的:
...
groups.each(function(data, idx) {
let key = data["key"];
let g = d3.select(this);
let parent = d3.select(this.parentNode);
//let center = that.getBoundingBoxCenter(g);
let children = g[0][0].childNodes;
let allPoints = [...Array(children.length)].map((child, idx) => {
return d3.transform(d3.select(children[idx]).attr("transform")).translate;
})
let center = that.getAveragePoint(allPoints);
...
在哪里getAveragePoint()
:
getAveragePoint = (vals) => {
let arrX = vals.map(arr => { return arr[0]; });
let arrY = vals.map(arr => { return arr[1]; });
let avgX = avg(arrX);
let avgY = avg(arrY);
let stDevX = stDev(arrX);
let stDevY = stDev(arrY);
let newArrX = arrX.filter(x => {
if (Math.abs(x - avgX) < stDevX) {
return true;
}
return false;
});
let newArrY = arrY.filter(y => {
if (Math.abs(y - avgY) < stDevY) {
return true;
}
return false;
});
let newAvgX = avg(arrX);
let newAvgY = avg(arrY);
return [newAvgX,newAvgY];
}
stDev
并且avg
只是在提供的数组中查找标准偏差和平均值的函数。真正有用的是以下线程:
要弄清楚最重要的一行:return d3.transform(d3.select(children[idx]).attr("transform")).translate
结果图表:
推荐阅读
- python - 为什么在 Django 视图中无法捕获异常以及如何调试
- php - PHP 选择下拉选项值数组
- laravel - laravel sendgrid 驱动程序中出现 cURL 错误 18 错误
- php - 将随机 URL 链接添加到随机背景图像
- javascript - 如何找到使用 Google Chrome 调试器调用 javascript 的位置?
- ios - 从多个视图控制器调用相同 API 的最佳方法是什么
- opengl-es - 需要一个关于鲁棒缓冲区访问何时有效的具体示例
- wso2 - 从 siddhi 上的 Tcp 接收 json 日志
- wso2 - 使用 wso2 6.4.0 dss 从多张单个 Excel 文件中检索数据并插入数据库
- javafx - 动画后无法从节点中删除子节点