首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >传说中标度(线性、幂、对数)的自动选择

传说中标度(线性、幂、对数)的自动选择
EN

Stack Overflow用户
提问于 2020-10-26 20:41:20
回答 1查看 80关注 0票数 2

这更多的是一个数据科学的问题,而不是d3.js,但我想其他人肯定也考虑过这个问题。

我有一个具有每日更新值的数据集。该集合还包含所有或几天的历史数据。基本上是这样的:

代码语言:javascript
复制
{data: [
    "ItemA" : {
        "24.10.2020" : 123,
        "25.10.2020" : 134,
        "26.10.2020" : 145,
        "27.10.2020" : 156,
        "28.10.2020" : 167      
    },
    "ItemB" : {
        "24.10.2020" : 123,
        "25.10.2020" : 234,
        "26.10.2020" : 456,
        "27.10.2020" : 567,
        "28.10.2020" : 678      
    },
    "ItemC" : {
        "24.10.2020" : 123,
        "25.10.2020" : 136,
        "26.10.2020" : 149,
        "27.10.2020" : 152,
        "26.10.2020" : 165,
        "28.10.2020" : 178      
    },
]}

正如您所看到的,ItemB是一个异常值,其值的增长要比其他项的值增长得快得多。

建立一个图表的比例来显示随着时间的增长是很容易的,只要数值以几乎相同的速度增长。一个d3.scaleLinear().domain([0, upperBoundValues])很好。当值增加时,用户仍然可以区分较小的值和较高的值。

由于一个项目增长得更快,增长较慢的项目被推到了规模的一个部分。因此,如果我有一个像d3.interpolateTurbo这样的颜色范围,那么大多数值都会被显示为接近黑色的颜色,而一个总是显示到红色的颜色。

我会手动切换到电源秤或者日志秤。尤其是因为我每天都要检查会发生什么。

我更希望有一个函数来测试这样的开发,并自动切换标度,如果值。更好的是,选择一个合适的标度(基本上选择幂标度和/或对数标度的最佳拟合指数)。如果我的值永远不会增长到超大值,我就不需要base10日志刻度。

是否有任何近似函数/算法可以使选择更容易,或者返回一个值,我可以选择标度(例如:0.1 ->线性/1.n ->日志)

EN

回答 1

Stack Overflow用户

发布于 2020-10-26 22:06:40

作为我的注释的扩展,请考虑以下内容,它使用带有十进制值的scaleThreshold。我画了5个圆圈,第一个圆圈的增值比其他的快得多。但你仍然会看到他们之间的差异,因为阈值尺度。

代码语言:javascript
复制
const data = d3.range(5).map(i => {
  let values = [1];
  d3.range(50).forEach(() => {
    // Either a multiplier [0.9, 1.2], or (if it's the first one, [1.2, 1.5]
    const multiplier = (i === 0 ? 1.2 : 0.9) + (Math.random() * 0.3);
    values.push(values[values.length - 1] * multiplier);
  });

  return {
    x: 50 + i * 100,
    y: 50,
    r: 40,
    values: values,
  };
});

const allValues = data.map(d => d.values).flat().sort((a, b) => a - b);
const colours = d3.scaleThreshold()
  .domain([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9].map(i => d3.quantile(allValues, i)))
  .range(d3.schemeSpectral[10]);

const svg = d3.select("svg")
  .attr("width", 500);

const colourbar = svg.append("g");

colourbar
  .selectAll("rect")
  .data(colours.range())
  .enter()
  .append("rect")
  .attr("x", (d, i) => i * 50)
  .attr("y", 100)
  .attr("height", 20)
  .attr("width", 50)
  .attr("fill", d => d);

colourbar
  .selectAll("text")
  .data(colours.domain())
  .enter()
  .append("text")
  .attr("x", (d, i) => (i + 1) * 50)
  .attr("y", 135)
  .text(d => d.toFixed(1));

const circles = svg.append("g")
  .selectAll("circle")
  .data(data)
  .enter()
  .append("circle")
  .attr("cx", d => d.x)
  .attr("cy", d => d.y)
  .attr("r", d => d.r);

const labels = svg
  .append("g")
  .selectAll("text")
  .data(data)
  .enter()
  .append("text")
  .style("fill", "white")
  .attr("dy", 5)
  .attr("x", d => d.x)
  .attr("y", d => d.y);

let counter = -1;

function colour() {
  counter = (counter + 1) % 50;
  labels.text(d => d.values[counter].toFixed(1));
  circles
    .transition()
    .duration(1000)
    .ease(d3.easeLinear)
    .attr("fill", d => colours(d.values[counter]))
    .filter((d, i) => i === 0)
    .on("end", colour);
}

colour();
代码语言:javascript
复制
text {
  text-anchor: middle;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg></svg>

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64544680

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档