首页 > 解决方案 > 将beeswarm与scalePoint结合

问题描述

我想创建一种分类蜂群图,其中我的观察结果(圆圈)在 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 年应该有 44yScale('ia')个集群,2yScale('im')个集群和 6 个集群yScale('qdlp'),以此类推。

但同样,这并没有成功,我不知道为什么。

问题

我应该如何调整我的视觉以允许具有基于 d3 的中心的单独群体.scalePoint()

标签: javascriptd3.js

解决方案


首先,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>


推荐阅读