首页 > 解决方案 > 在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中实现?

标签: javascriptd3.js

解决方案


我能够确定每个集群内每个单点的位置,然后排除在xor上高于 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只是在提供的数组中查找标准偏差和平均值的函数。真正有用的是以下线程:

如何获取 svg 元素的坐标?

要弄清楚最重要的一行:return d3.transform(d3.select(children[idx]).attr("transform")).translate

结果图表:

在此处输入图像描述


推荐阅读