D3 顺序尺度和线性尺度之间的区别
D3 difference between ordinal and linear scales
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,returns 输出范围中的对应值。
如果明确指定范围(如范围,但不是 rangeBands、rangeRoundBands 或 rangePoints),并且给定值 x 不在比例尺的域中,则 x 被隐式添加到域中;给定相同值 x 的后续调用将 return 范围内的相同值 y。
d3.scale.linear()
构造一个新的线性比例尺,默认域为[0,1],默认范围为[0,1]。因此,默认的线性比例相当于数字的恒等函数;例如 linear(0.5) returns 0.5.
在 D3.js 中,标度将数字从定义域转换为范围。对于线性标度,域将是一个连续变量,具有无限范围的值,然后可以将其转换为连续范围。对于序数尺度,将有一个离散域,例如一年中的月份,其中可能的值范围有限,可以排序但不连续。 API docs on Github 可能比我
更能解释差异
Ordinal scales have a discrete domain, such as a set of names or categories.
An ordinal scale's values must be coercible to a string, and the stringified version of the domain value uniquely identifies the corresponding range value.
因此,例如,序数范围的域可能包含名称,如下所示:
var ordinalScale = d3.scale.ordinal()
.domain(['Alice', 'Bob'])
.range([0, 100]);
ordinalScale('Alice'); // 0
ordinalScale('Bob'); // 100
注意所有值都是字符串。它们不能被插值。 'Alice' 和 'Bob' 之间是什么?我不知道。 D3 也没有。
现在,至于Quantitative Scales(例如线性标尺):
Quantitative scales have a continuous domain, such as the set of real numbers, or dates.
例如,您可以构建以下比例:
var linearScale = d3.scale.linear()
.domain([0, 10])
.range([0, 100]);
linearScale(0); // 0
linearScale(5); // 50
linearScale(10); // 100
注意 D3 如何能够插入 5,即使我们没有在域中明确指定它。
查看 this jsfiddle 以查看上面的代码。
好的,我们可以开始学习它,使用相同的数据来查看差异(我使用的是 d3 v4),假设我们有以下使用 ordinal
和 linear
的数据体重秤:
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) 将 return 20...我们的域最大值是 100,100 除以 5 等于 20,所以 scaleLinear(1)是 20 和 scaleLinear(2) 是 40...
但是如您所见,scaleOrdinal(1) 映射到范围内的数组,因此它等于 one 和 scaleOrdinal(2) 它等于 two...
这就是您可以使用这些比例的方法,scaleLinear 对很多事情都很有用,包括在页面上显示比例,但 scaleOrdinal 更多对于按顺序获取数据很有用,文档中就是这样解释的:
# d3.scaleLinear() <>
Constructs a new continuous scale with the unit domain [0, 1], the
unit range [0, 1], the default interpolator and clamping disabled.
Linear scales are a good default choice for continuous quantitative
data because they preserve proportional differences. Each range value
y can be expressed as a function of the domain value x: y = mx + b.
d3.scaleOrdinal([range]) <>
Constructs a new ordinal scale with an empty domain and the specified
range. If a range is not specified, it defaults to the empty array; an
ordinal scale always returns undefined until a non-empty range is
defined.
这也是 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>
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,returns 输出范围中的对应值。
如果明确指定范围(如范围,但不是 rangeBands、rangeRoundBands 或 rangePoints),并且给定值 x 不在比例尺的域中,则 x 被隐式添加到域中;给定相同值 x 的后续调用将 return 范围内的相同值 y。
d3.scale.linear()
构造一个新的线性比例尺,默认域为[0,1],默认范围为[0,1]。因此,默认的线性比例相当于数字的恒等函数;例如 linear(0.5) returns 0.5.
在 D3.js 中,标度将数字从定义域转换为范围。对于线性标度,域将是一个连续变量,具有无限范围的值,然后可以将其转换为连续范围。对于序数尺度,将有一个离散域,例如一年中的月份,其中可能的值范围有限,可以排序但不连续。 API docs on Github 可能比我
更能解释差异Ordinal scales have a discrete domain, such as a set of names or categories.
An ordinal scale's values must be coercible to a string, and the stringified version of the domain value uniquely identifies the corresponding range value.
因此,例如,序数范围的域可能包含名称,如下所示:
var ordinalScale = d3.scale.ordinal()
.domain(['Alice', 'Bob'])
.range([0, 100]);
ordinalScale('Alice'); // 0
ordinalScale('Bob'); // 100
注意所有值都是字符串。它们不能被插值。 'Alice' 和 'Bob' 之间是什么?我不知道。 D3 也没有。
现在,至于Quantitative Scales(例如线性标尺):
Quantitative scales have a continuous domain, such as the set of real numbers, or dates.
例如,您可以构建以下比例:
var linearScale = d3.scale.linear()
.domain([0, 10])
.range([0, 100]);
linearScale(0); // 0
linearScale(5); // 50
linearScale(10); // 100
注意 D3 如何能够插入 5,即使我们没有在域中明确指定它。
查看 this jsfiddle 以查看上面的代码。
好的,我们可以开始学习它,使用相同的数据来查看差异(我使用的是 d3 v4),假设我们有以下使用 ordinal
和 linear
的数据体重秤:
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) 将 return 20...我们的域最大值是 100,100 除以 5 等于 20,所以 scaleLinear(1)是 20 和 scaleLinear(2) 是 40...
但是如您所见,scaleOrdinal(1) 映射到范围内的数组,因此它等于 one 和 scaleOrdinal(2) 它等于 two...
这就是您可以使用这些比例的方法,scaleLinear 对很多事情都很有用,包括在页面上显示比例,但 scaleOrdinal 更多对于按顺序获取数据很有用,文档中就是这样解释的:
# d3.scaleLinear() <>
Constructs a new continuous scale with the unit domain [0, 1], the unit range [0, 1], the default interpolator and clamping disabled. Linear scales are a good default choice for continuous quantitative data because they preserve proportional differences. Each range value y can be expressed as a function of the domain value x: y = mx + b.
d3.scaleOrdinal([range]) <>
Constructs a new ordinal scale with an empty domain and the specified range. If a range is not specified, it defaults to the empty array; an ordinal scale always returns undefined until a non-empty range is defined.
这也是 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>