D3序数和线性标度之间的差异

时间:2015-04-21 23:53:23

标签: javascript d3.js

var xScale = d3.scale.ordinal().domain([0, d3.max(data)]).rangeRoundBands([0, w], .1);
var yScale = d3.scale.linear().domain([0, data.length]).range([h, 0]);

我对在D3中何时使用序数线性比例感到困惑。

以下是我从API文档中发现的内容,仍然有点遗失......如果有人可以提供帮助,我们将不胜感激。

序(x)的

在输入域中给定值x,返回输出范围中的相应值。

如果显式指定范围(通过范围,但不是rangeBands,rangeRoundBands或rangePoints),并且给定值x不在比例的域中,则x被隐式添加到域中;如果给定相同值x的比例的后续调用将从范围返回相同的值。

d3.scale.linear()

使用默认域[0,1]和默认范围[0,1]构造一个新的线性刻度。因此,默认线性标度等同于数字的标识函数;例如,线性(0.5)返回0.5。

3 个答案:

答案 0 :(得分:74)

至于Ordinal Scales

  

序数量表具有离散域,例如一组名称或类别。

     

序数比例的值必须对字符串具有可强制性,域值的字符串化版本唯一标识相应的范围值。

因此,作为一个例子,序数量表的域可能包含名称,如下所示:

var ordinalScale = d3.scale.ordinal()
        .domain(['Alice', 'Bob'])
        .range([0, 100]);

ordinalScale('Alice'); // 0
ordinalScale('Bob'); // 100

注意所有值都是字符串。它们无法插值。 'Alice'和'Bob'之间有什么关系?我不知道。 D3也没有。

现在,至于Quantitative Scales(例如线性比例):

  

定量比例具有连续域,例如实数或日期集。

例如,您可以构建以下比例:

var linearScale = d3.scale.linear()
        .domain([0, 10])
        .range([0, 100]);

linearScale(0); // 0
linearScale(5); // 50
linearScale(10); // 100

注意D3即使我们没有在域中明确指定它也能够插入5。

请查看this jsfiddle以查看上述代码。

答案 1 :(得分:3)

在D3.js中,将一个数字从域转换为范围。对于线性比例,域将是连续变量,具有无限范围的值,然后可以将其转换为连续范围。对于序数量表,将存在离散域,例如一年中的几个月,其中可能的值范围有限但可能是连续的。 API docs on Github可能比我有更好的解释差异

答案 2 :(得分:1)

好的,我们可以开始学习它,同时使用相同的数据来查看差异(我正在使用d3 v4),想象我们使用ordinallinear比例来获得以下数据:

const data = [1, 2, 3, 4, 5];

const scaleLinear = d3.scaleLinear()
  .domain([0, Math.max(...data)]).range([1, 100]);

const scaleOrdinal = d3.scaleOrdinal()
  .domain(data).range(['one', 'two', 'three', 'four', 'five']);

现在我们开始调用它们来查看结果:

scaleLinear(1); //20
scaleOrdinal(1); //one

scaleLinear(2); //40
scaleOrdinal(2); //two

scaleLinear(5); //100
scaleOrdinal(5); //five

查看我们得到的函数和结果,正如您在序数中看到的那样,我们将数据映射到我们的范围,而在线性的那个我们延伸到范围,因此在这些情况下例如 scaleLinear( 1)将返回20 ...我们的域名最大值为100且100除以5等于20,因此 scaleLinear(1) 20 scaleLinear(2) 40 ...

但如您所见, scaleOrdinal(1)映射到范围内的数组,因此它等于一个 scaleOrdinal(2)它等于两个 ......

因此,您可以使用这些比例, scaleLinear 对许多内容都很有用,包括在页面上显示比例,但 scaleOrdinal 对于按顺序获取数据更有用,这就是它在文档中的解释:

  

#d3.scaleLinear()<>

     

使用单位域[0,1]构造一个新的连续标度   单位范围[0,1],默认插补器和钳位禁用。   线性刻度是连续定量的良好默认选择   数据,因为它们保持比例差异。每个范围值   y可以表示为域值x的函数:y = mx + b。


  

d3.scaleOrdinal([range])<>

     

使用空域和指定的构造新的序数比例   范围。如果未指定范围,则默认为空数组;一个   序数比例始终返回undefined,直到非空范围为止   定义

同样,这是d3同时使用序数和线性尺度的一个很好的例子:

var myData = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

var linearScale = d3.scaleLinear()
  .domain([0, 11])
  .range([0, 600]);

var ordinalScale = d3.scaleOrdinal()
  .domain(myData)
  .range(['black', '#ccc', '#ccc']);

d3.select('#wrapper')
  .selectAll('text')
  .data(myData)
  .enter()
  .append('text')
  .attr('x', function(d, i) {
    return linearScale(i);
  })
  .text(function(d) {
    return d;
  })
  .style('fill', function(d) {
    return ordinalScale(d);
  });
body {
  font-family: "Helvetica Neue", Helvetica, sans-serif;
  font-size: 14px;
  color: #333;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>

<svg width="800" height="60">
  	<g id="wrapper" transform="translate(100, 40)">
  	</g>
</svg>