我需要在d3中建立一个带有离散数据点的小提琴点。
示例:
我不确定如何在X轴上对齐每个值的中心。默认行为将覆盖具有相同X和Y值的所有点,但是我希望这些点在中心对齐时偏移,例如, 5.1在控制组中有3个值,4.5有2个值,所有中心对齐。通过将每个点转换指定的量,可以很容易地进行右对齐或左对齐。然而,中心对齐似乎很苛刻。
一种hacky方式是通过维护几个数组来手动转换X值,以查看这是第一个,偶数还是奇数个元素,并根据我指定的值放置它。有没有正确的方法来解决这个问题?
我发现d3中唯一的小提琴情节示例是here - 它实现了概率分布而不是我需要的离散值。
答案 0 :(得分:2)
“一种hacky方式是通过维护几个数组手动转换X值” - 这几乎是大多数d3布局的工作方式:-)。通过y值(权重)对数据集进行分散,保留每个离散组中的数据点总数以及每个数据的组索引。然后使用它们来计算偏移x-way和舍入的y值。
请参阅https://jsfiddle.net/n444k759/4/
// below code assumes a svg and g group element are present (they are in the jsfiddle)
var yscale = d3.scale.linear().domain([0,10]).range([0,390]);
var xscale = d3.scale.linear().domain([0,2]).range ([0,390])
var color = d3.scale.ordinal().domain([0,1]).range(["red", "blue"]);
var data = [];
for (var n = 0; n <100; n++) {
data.push({weight: Math.random() * 10.0, category: Math.floor (Math.random() * 2.0)});
}
var groups = {};
var circleR = 5;
var discreteTo = (circleR * 2) / (yscale.range()[1] / yscale.domain()[1]);
data.forEach (function(datum) {
var g = Math.floor (datum.weight / discreteTo);
var cat = datum.category;
var ref = cat+"-"+g;
if (!groups[ref]) { groups[ref] = 0; }
datum.groupIndex = groups[ref];
datum.discy = yscale (g * discreteTo); // discrete
groups[ref]++;
});
data.forEach (function(datum) {
var cat = datum.category;
var g = Math.floor (datum.weight / discreteTo);
var ref = cat+"-"+g;
datum.offset = datum.groupIndex - ((groups[ref] - 1) / 2);
});
d3.select("svg g").selectAll("circle").data(data)
.enter()
.append("circle")
.attr("cx", function(d) { return 50 + xscale(d.category) + (d.offset * (circleR * 2)); })
.attr("r", circleR)
.attr("cy", function(d) { return 10 + d.discy; })
.style ("fill", function(d) { return color(d.category); })
;
上述示例根据显示的大小和要显示的圆的大小分组。您可能希望按给定间隔离散,然后从中计算出圆的大小。
修改:已更新,以显示如何区分何时类别不同,如上面的屏幕截图