我想创建一种分类蜂群图,其中我的观测值(圆)在x轴上按年排列,在y轴上按类型分类。我个人认为.scalePoint()
更易于使用,但是我开始认为我可能无法在特定的应用程序中使用它。这是我的代码:
var margins = {top:20, bottom:300, left:30, right:100};
var height = 400;
var width = 1000;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");
var xScale = d3.scalePoint()
.range([0, width]);
var data = [
{'year':'2002', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'im'},
{'year':'2013', 'type':'im'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'}
];
var colorScale = d3.scaleLinear()
.range(["#e7eef8","#003366"]);
xScale.domain(['','2002','2013','2016','2017','2018','2019']);
var colorMap = {
'ia':"#003366",
'im':"#b8cce4",
'qdlp':"#4f81b9"
};
var yScale = d3.scalePoint()
.range([height,0])
.domain(['','ia','im','qdlp']);
data.forEach(function (d) {
d.x = xScale(d.year);
d.y = yScale(d.type);
});
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(function(d) {
return xScale(d.year);
}).strength(0.05))
.force("y", d3.forceY(function(d) {
return yScale(d.type);
}).strength(0.1))
.force("collide", d3.forceCollide(4).iterations(1))
.stop();
for (var i = 0; i < 484; ++i) {
simulation.tick();
data.forEach(function (d) {
if (d.type) {
d.y = yScale(d.y);
} else {
d.y = yScale(d.y);
}
});
}
graphGroup.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
graphGroup.append("g")
.attr("class", "axis axis--y")
.attr("transform", "translate(0," + 0 + ")")
.call(d3.axisRight(yScale));
var circles = graphGroup.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("r", 3)
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.style('fill', function(d) {return colorMap[d.type] });
<script src="https://d3js.org/d3.v5.min.js"></script>
您会注意到我所有的圆都分配了相同的y值。不仅在其他两个类别上没有附加任何圆,而且根本没有蜂群组。由于某些原因,所有圆都彼此叠加。
我期望它们根据它们的x和y坐标以温暖的方式排列。例如,2002年应该只有一个圆圈; 2013年应该在
yScale('ia')
处具有44个群集,在yScale('im')
处具有2个群集,在yScale('qdlp')
处具有6个群集,依此类推。但是,这并没有成功,我不确定为什么。
题
我应该如何调整视觉以允许以d3的
.scalePoint()
为中心的单独群体? 最佳答案
首先,毫无疑问,d3.scalePoint
是完成任务的最佳选择。
回到问题,这段代码在每个刻度之后运行。
data.forEach(function (d) {
if (d.type) {
d.y = yScale(d.y);
} else {
d.y = yScale(d.y);
}
});
...不仅覆盖了模拟,而且更糟糕的是,您正在将数字传递给以字符串为域的点刻度。
解决方案再简单不过了:将其删除。
var margins = {top:20, bottom:300, left:30, right:100};
var height = 400;
var width = 1000;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");
var xScale = d3.scalePoint()
.range([0, width]);
var data = [
{'year':'2002', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'ia'},
{'year':'2013', 'type':'im'},
{'year':'2013', 'type':'im'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2013', 'type':'qdlp'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'ia'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'im'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'},
{'year':'2016', 'type':'qdlp'}
];
var colorScale = d3.scaleLinear()
.range(["#e7eef8","#003366"]);
xScale.domain(['','2002','2013','2016','2017','2018','2019']);
var colorMap = {
'ia':"#003366",
'im':"#b8cce4",
'qdlp':"#4f81b9"
};
var yScale = d3.scalePoint()
.range([height,0])
.domain(['','ia','im','qdlp']);
data.forEach(function (d) {
d.x = xScale(d.year);
d.y = yScale(d.type);
});
var simulation = d3.forceSimulation(data)
.force("x", d3.forceX(function(d) {
return xScale(d.year);
}).strength(0.05))
.force("y", d3.forceY(function(d) {
return yScale(d.type);
}).strength(0.1))
.force("collide", d3.forceCollide(4).iterations(1))
.stop();
for (var i = 0; i < 484; ++i) {
simulation.tick();
}
graphGroup.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
graphGroup.append("g")
.attr("class", "axis axis--y")
.attr("transform", "translate(0," + 0 + ")")
.call(d3.axisRight(yScale));
var circles = graphGroup.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("r", 3)
.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
})
.style('fill', function(d) {return colorMap[d.type] });
<script src="https://d3js.org/d3.v5.min.js"></script>