2014-10-04 76 views
3

我用D3做了散点图。我如何识别剧情中人口最多的地区,并用椭圆包围它们。例如,在波纹管图的右上角有2个人口稠密的点。有没有一个功能可以做到这一点?如果不是,我对两件事的建议感激:识别,包围或以任何方式标记它们。D3:散点图中人口最多的区域

Scater plot http://tetet.net/clusterLab/scatter.png

var width = 300, 
    height = 200; 

var x = d3.scale.linear().range([0, width]), 
    y = d3.scale.linear().range([height, 0]); 

var svg = d3.select("body") 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height); 

d3.tsv("data.tsv", function(error, data) { 
    if (error) console.warn(error); 
    x.domain(d3.extent(data, function(q) {return q.xCoord;})); 
    y.domain(d3.extent(data, function(q) {return q.yCoord;})); 

    svg.selectAll("circle") 
     .data(data) 
     .enter().append("circle") 
      .attr("r", 5) 
      .attr("cx", function(d) { return x(d.xCoord); }) 
      .attr("cy", function(d) { return y(d.yCoord); }) 
}); 

数据

xCoord yCoord 
0 0 
5 3 
2 1 
4 7 
7 4 
5 2 
9 9 
3 4 
1 6 
5 4 
8.1 6.2 
8.4 6.6 
8 6 
8 7 
7 8 
6.8 8.3 
6.4 8.4 
6.2 8.3 
+0

一个简单的思考椭圆的方法,如果每个簇中没有多个点:遍历一个簇中的所有点对以找到彼此距离最远的一对点。在这两点之间的直线上构造一个具有焦点的椭圆的公式,例如,使用[这些答案](http://math.stackexchange.com/questions/426150/what-is-the-general-equation-of-the-ellipse-that-is-not-in-the-origin-and-旋转)。调整参数,使椭圆包括集群中的所有点,但不能变窄(从包含两个点的圆大到足够大)。 – Mars 2014-10-04 17:02:07

回答

3

a number of clustering algorithms在那里。我将以OPTICS algorithm(我真的是随机挑选它)为例来举例说明,并用一种​​方法来标记每个群集具有唯一颜色的点。

请注意,我正在使用npm上的density-clustering软件包。

一旦加载和分析数据(但在此之前,我们在屏幕上绘制的任何东西),让我们设置的算法:

var optics = new OPTICS(), 

    // The algorithm requires a dataset of arrays of points, 
    // so we need to create a modified copy of our original data: 
    opticsData = data.map(function (d) { 
     return [d.xCoord, d.yCoord]; 
    }), 

    // Algorithm configuration: 
    epsilon = 2, // min distance between points to be considered a cluster 
    minPts = 2, // min number of points in a cluster 

    // Now compute the clusters: 
    clusters = optics.run(opticsData, epsilon, minPts); 

现在我们可以与集群所属的信息标志着我们的原始数据点至。一个很粗的解决方案...你可能想到的东西更优雅:

clusters.forEach(function (cluster, clusterIndex) { 
    cluster.forEach(function (index) { 
     // data is our original dataset: 
     data[index].cluster = clusterIndex; 
    }); 
}); 

现在让我们创建一个非常简单的色标,并把它应用到我们的观点:

var colorScale = d3.scale.category20(); 

// Some code omitted for brevity: 
...enter().append("circle") 
    ... 
    .style('fill', function (d) { 
     return colorScale(d.cluster); 
    }); 

你可以看看demo。我必须按原样包含库,因此您需要滚动到JavaScript面板的底部,对不起。

3

如果您只需要一个可视化表示,并且不需要计算位置或中心或类似的东西,那么解决方案可能非常简单。除了代表数据点的现有圆圈之外,还要让每个数据点绘制一个半透明的大圆。如果这些较大的圆圈重叠,交叉点将会变暗,并且越重叠越深,它将会得到(假设您保持背景为白色)。你可以非常大小的圆圈,它们的颜色和不透明度/透明度。