【问题标题】:D3: Are "parabolic" scales possible?D3:“抛物线”尺度可能吗?
【发布时间】:2017-05-26 17:35:13
【问题描述】:

我正在制作一个图表,其中每个观察值的值都在[-100,100] 之间,我想在比例尺上绘制每个点的位置。挑战在于,绝大多数点在尺度的一个区域内都有值(分布本质上是均值为 0 的高斯分布)。

过去,当我需要绘制类似 Zipf 概率密度分布的图时,我会使用对数标度来分散拥挤区域中的点。现在我的情况类似,除了我有两个分布需要分散点(来自[0, max] 的正比例和来自[0, min] 的镜像负比例)。

我知道我可以为正值创建一个比例,为负值创建一个比例,但我想知道是否可以只用一个比例来实现这种布局。似乎抛物线刻度之类的东西可以在这里提供帮助(如果存在的话)。有没有可能在 D3 中实现这样的东西?

【问题讨论】:

  • I've used log scales to spread out the points in congested region 我想听听更多关于这方面的信息,因为乍一看,这听起来像是在扭曲图表,从而导致对数据的误解。
  • @vol7ron 对数刻度并不罕见——向用户展示对数刻度很重要,以便他们了解分布/数据。这是一个示例:bl.ocks.org/mbostock/5537697
  • 我不一定同意那个时候的观点,但是一个快速的谷歌让我闭嘴。我可以看到实际的例子,尤其是对于更高层次的数学。其他示例包括地图,对数密度阴影似乎更合适。

标签: javascript d3.js data-visualization


【解决方案1】:

在解释我提出的解决方案之前,关于这个问题中的 cmets 的一些注意事项:您不能在您的情况下使用对数刻度。这是一个简单的数学原理:Log(0) 是负无穷大。实际上,这在docs中明确说明:

由于 log(0) = -∞,对数尺度域必须是严格正数或严格负数;域不得包含或交叉零。

话虽如此,让我们看看建议的解决方案。

您可以创建自己的规模(没那么复杂)。但是,在这里,我将使用 interpolate 函数,基于此 excellent answer(但不是重复的,因为您想要相反)和此 code from Mike Bostock

使用线性比例,我们设置一个插值器:

var xScale = d3.scaleLinear()
    .domain([-100, 100])
    .interpolate(easeInterpolate(d3.easeQuadInOut));

然后,我们在easeInterpolate 函数中使用easing

function easeInterpolate(ease) {
    return function(a, b) {
        var i = d3.interpolate(a, b);
        return function(t) {
            return i(ease(t));
        };
    };
}

我在这里使用d3.easeQuadInOut,我认为它适合您,但您可以将其更改为另一个,甚至创建您自己的。

看看这个演示。我正在创建 50 个圆圈,均匀分布在 -100 到 +100 之间(-100、-96、-92、-88 ......直到 +100)。您可以看到它们已从中心移开。如果您对数据使用此比例,您将避免零附近的拥挤数据点:

var data = d3.range(51).map(function(d) {
  return -100 + (d * 4)
});

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

var xScale = d3.scaleLinear()
  .domain([-100, 100])
  .range([20, 580])
  .interpolate(easeInterpolate(d3.easeQuadInOut));

svg.append("g")
  .attr("transform", "translate(0,70)")
  .call(d3.axisBottom(xScale));

svg.selectAll(null)
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", function(d) {
    return xScale(d)
  })
  .attr("cy", 50)
  .attr("r", 4)
  .attr("fill", "teal")

function easeInterpolate(ease) {
  return function(a, b) {
    var i = d3.interpolate(a, b);
    return function(t) {
      return i(ease(t));
    };
  };
}
<script src="https://d3js.org/d3.v4.min.js"></script>

如果你问,最后一个勾号不是80100。这只是 80 刻度与 100 刻度重叠(-80-100 也会发生同样的事情)。

另外,值得注意的是,使用转换比例并没有错,即使它使图表变形歪斜,它也是完全有效的并且确实不会导致误解,只要您告知用户有关转换。

【讨论】:

  • 感谢您指出这一点。近年来,我不需要做任何高级图表。主要是简单的数据可视化,可以使用 C3(简化的 D3)或 Highcharts。我相信我会在未来几年重新审视这个问题和答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-27
  • 2011-07-02
  • 1970-01-01
  • 2014-11-26
  • 2013-02-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多