如何根据聚合数据预先计算 alpha 水平?

How do I pre-calculate an alpha level from aggregated data?

下面的 svg 代码绘制了四个点,由于点重叠,每个点的透明度都不同。

数据由圆圈的位置和位于该位置的圆圈数组成。这里的演示数据还表明,由于各种原因,这种聚合并不完美——它们可能是同一位置的两个条目,都表明那里有几个圆圈。

我想计算并显示实际透明度,就好像我以完全未聚合的形式获得数据一样 - 例如在此示例数据集中,未聚合形式将在位置 3 处为圆圈提供三个条目,并且在位置 3 处圆圈的透明度将与在位置 3 处圆圈的透明度相同=13=].

如何计算每个点应使用的 alpha 水平以获得此结果?请注意,我不想事先操作数据以获得未聚合的形式,因为它被聚合的原因是为了防止绘制大量 svg 元素,这将是非常密集的处理。

<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <script src="http://d3js.org/d3.v3.min.js"></script>
    </head>
    <body>
        <svg id="canvas"></svg>
        <script>
         var svg = d3.select("#canvas");
            svg.selectAll("circle")
                .data(
                        [
                            [1,1], 
                            [2,6], 
                            [3,1],
                            [3,2],
                            [4,1],
                            [4,1],
                            [4,1]
                        ]
                    )
            .enter().append("circle")
                .attr("cy", 60)
                .attr("cx", function(d) { return d[0] * 50; })
                .attr("r", 20)
                .attr("stroke-opacity", 0.3)
                .attr("fill-opacity", 0.3);
         </script>

    </body>
</html>

基本上,您需要对给定位置的所有圆求和(即在位置 3 有 1+2 = 3,位置 4 = 1+1+1 = 3),然后除以每个位置的圆圈数(位置 3 = 2,位置 4 = 3)。这应该为您提供一致的值来计算各个圆圈的不透明度。请参阅下面的代码段。有趣的一点是:

function opacity(d) {
    var count = data.filter(function(e) { return e[0] == d[0]; }).length,
    sum = d3.sum(data.filter(function(e) { return e[0] == d[0]; }), function(e) { return e[1]; });
    return (sum * .1) / count;
}  

var data =  [
                            [1,1], 
                            [2,6], 
                            [3,1],
                            [3,2],
                            [4,1],
                            [4,1],
                            [4,1]
                        ]
function opacity(d) {
    var count = data.filter(function(e) { return e[0] == d[0]; }).length,
    sum = d3.sum(data.filter(function(e) { return e[0] == d[0]; }), function(e) { return e[1]; });
    return (sum * .1) / count;
}  

var svg = d3.select("#canvas");
            svg.selectAll("circle")
                .data(data)
            .enter().append("circle")
                .attr("cy", 60)
                .attr("cx", function(d) { return d[0] * 50; })
                .attr("r", 20)
                .attr("stroke-opacity", opacity)
                .attr("fill-opacity", opacity);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg id="canvas"></div>