d3-array
JavaScript中的数据通常由数组表示,因此当进行可视化操作或数据分析时,人们倾向于操作数组。一些常见的操作形式包括使用数组的连续切片(子集)、使用predicate function(判定函数)过滤数组,以及使用转换函数将数组映射到一组并行值。在查看该模块提供的功能之前,请熟悉内置于JavaScript中强大的数组方法。
JavaScript中修改数组的方法:
- array.pop - 删除数组中的最后一个元素
- array.push - 向数组的末尾添加一个或多个元素
- array.reverse - 反转数组中元素的顺序
- array.shift - 删除数组中的第一个元素
- array.sort - 对数组元素进行排序
- array.splice - 向数组添加或删除元素
- array.unshift - 向数组的开头添加一个或多个元素
还有一些访问方法返回数组的一些表示形式:
- array.concat - 将数组与其他数组或值进行连接
- array.join - 将数组中的所有元素连接成字符串
- array.slice - 提取数组中的部分元素
- array.indexOf - 查找数组中某个值第一次出现的位置索引
- array.lastIndexOf - 查找数组中某个值最后一次出现的位置索引
以及对数组元素应用函数的迭代方法:
- array.filter - 用数组中判定为真的元素创建一个新数组
- array.forEach - 为数组中的每个元素调用一个函数
- array.every - 检测数组中是否每个元素都判定为真
- array.map - 为数组中的每个元素调用一个函数,并以结果创建一个新数组
- array.some - 检测数组中是否至少有一个元素判定为真
- array.reduce - 应用函数将数组缩减为一个值(从左到右)
- array.reduceRight - 应用函数将数组缩减为一个值(从右到左)
Installing
如果你使用npm,请键入npm install d3-array
。否则,请下载最新版本。你也可以直接从d3js.org加载,作为standalone library(独立库)或D3 4.0的一部分来使用。支持AMD,CommonJS和vanilla环境。在vanilla环境下,会输出一个全局的d3
:
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script>
var min = d3.min(array);
</script>
API Reference
Statistics
一些用于基本汇总统计的计算方法。
d3.min(array[,accessor])
使用自然顺序返回给定array中的最小值。如果array为空,则返回undefined。可以指定一个accessor函数,相当于在计算最小值前调用array.map(accessor)。
与内置的Math.min不同的是,此方法会忽略undefined、null和NaN,这对于需要忽略缺失数据时非常有用。此外,元素使用的是自然顺序进行比较而不是数字顺序。例如:["20","3"]的最小值是“20”,而[20,3]的最小值是3。
var a = ["20", "3"];
var b = [20, 3];
d3.min(a); // "20"
d3.min(b); // 3
d3.max(array[,accessor])
使用自然顺序返回给定array中的最大值。如果array为空,则返回undefined。可以指定一个accessor函数,相当于在计算最大值前调用array.map(accessor)。
与内置的Math.max不同的是,此方法会忽略undefined、null和NaN,这对于需要忽略缺失数据时非常有用。此外,元素使用的是自然顺序进行比较而不是数字顺序。例如:["20","3"]的最大值是“3”,而[20,3]的最大值是20。
var a = ["20", "3"];
var b = [20, 3];
d3.max(a); // "3"
d3.max(b); // 20
d3.extent(array[,accessor])
使用自然顺序返回给定array中的最小值和最大值。如果array为空,则返回[undefined,undefined]。可以指定一个accessor函数,相当于在计算最值前调用array.map(accessor)。
var a = ["20", "3", "14", "5"];
var b = [20, 3, 14, 5];
var c = [];
d3.extent(a); // ["14", "5"]
d3.extent(b); // [3, 20]
d3.extent(c); // [undefined, undefined]
d3.sum(array[,accessor])
返回给定数字array的和。如果array为空,则返回0。可以指定一个accessor函数,相当于在求和前调用array.map(accessor)。此方法会忽略undefined和NaN;这对于需要忽略缺失数据时非常有用。
var a = [20, 3, 14, 5];
d3.sum(a); // 42
d3.mean(array[,accessor])
返回给定数字array的算数平均数。如果array为空,则返回undefined。可以指定一个accessor函数,相当于在求算数平均数前调用array.map(accessor)。此方法会忽略undefined和NaN;这对于需要忽略缺失数据时非常有用。
var a = [20, 3, 14, 5];
d3.mean(a); // 10.5
d3.median(array[,accessor])
使用R-7 method(R-7方法)返回给定数字array的中位数。如果array为空,则返回undefined。可以指定一个accessor,相当于在求中位数前调用array.map(accessor)。此方法会忽略undefined和NaN;这对于需要忽略缺失数据时非常有用。
var a = [20, 3, 14, 5];
d3.median(a); // 9.5
d3.quantile(array, p[, accessor])
返回给定有序数字array的p-分位数,p的取值范围在[0,1]之间。例如:中位数可以通过p=0.5计算得出,则第一个四分位数在p=0.25处,第三个四分位数在p=0.75处。这个特定的实现使用了R-7 method(R-7方法),该方法也是编程语言R和Excel的默认方法。例如:
var a = [0, 10, 30];
d3.quantile(a, 0); // 0
d3.quantile(a, 0.5); // 10
d3.quantile(a, 1); // 30
d3.quantile(a, 0.25); // 5
d3.quantile(a, 0.75); // 20
d3.quantile(a, 0.1); // 2
可以指定一个accessor函数,相当于在求分位数前调用array.map(accessor)。
d3.variance(array[, accessor])
返回给定数组array的unbiased estimator of the population variance(总体方差的无偏估计)。如果array的元素少于两个,则返回undefined。可以指定一个accessor函数,相当于在计算variance(方差)前调用array.map(accessor)。此方法会忽略undefined和NaN;这对于需要忽略缺失数据时非常有用。
var a = [20, 3, 14, 5];
d3.variance(a); // 63
d3.deviation(array[, accessor])
返回给定数组array的standard deviation(标准差),定义为bias-corrected variance(偏置校正方差)的平方根。如果array的元素少于两个,则返回undefined。可以指定一个accessor函数,相当于在计算标准差前调用array.map(accessor)。此方法会忽略undefined和NaN;这对于需要忽略缺失数据时非常有用。
var a = [20, 3, 14, 5];
d3.variance(a); // 7.937253933193772
Search
用于在数组中搜索特定元素的方法。
d3.scan(array[, comparator])
对指定array执行线性扫描,根据给定的comparator返回最小元素的索引。如果给定array中包含无法比较的元素(也就是说,当每个元素同其自身进行比较时,comparator返回NaN),则返回undefined。如果不指定comparator,则默认为升序。例如:
var array = [{foo: 42}, {foo: 91}];
d3.scan(array, function(a, b) { return a.foo - b.foo; }); // 0
d3.scan(array, function(a, b) { return b.foo - a.foo; }); // 1
此函数类似于min,但它可以使用comparator而不是accessor,并且返回的是索引而不是值。另请参阅bisect。
d3.bisectLeft(array, x[, lo[, hi]])
返回array中x的插入点以保持排序顺序。可以使用lo和hi参数指定array的子集,默认情况下对整个array使用。如果x已经在array中,插入点将在任何现有条目之前(在左边)。如果array已经排序,则返回值适合用作splice的第一个参数。返回的插入点i将array分割为两半,左边为v < x(v为array.slice(lo,i)中的值)的部分,右边为v >= x(v为array.slice(i,hi)中的值)的部分。
d3.bisect(array, x[, lo[, hi]])
d3.bisectRight(array, x[, lo[, hi]])
与bisectleft类似,但是返回现有元素x从右向左的插入点。返回的值i将数组分割为两半,左边为v <= x(v为array.slice(lo,i)中的值)的部分,右边为v > x(v为array.slice(i,hi)中的值)的部分。
d3.bisector(accessor)
d3.bisector(comparator)
返回使用指定accessor或comparator函数生成一个新的bisector(二等分线)。此方法可作用于对象数组,而不是仅仅局限于简单数组。例如,给定以下对象数组:
var data = [
{date: new Date(2011, 1, 1), value: 0.5},
{date: new Date(2011, 2, 1), value: 0.6},
{date: new Date(2011, 3, 1), value: 0.7},
{date: new Date(2011, 4, 1), value: 0.8}
];
构建一个适用的二等分函数如下:
var bisectDate = d3.bisector(function(d) { return d.date; }).right;
这相当于指定一个comparator:
var bisectDate = d3.bisector(function(d, x) { return d.date - x; }).right;
然后应用bisectDate(array,date)
,返回一个索引。注意,comparator总是将搜索值x作为第二个参数传递。如果你希望值的排序方式与自然顺序不一样,可以使用comparator而不是accessor,如以降序排列而不是升序。
bisector.left(array, x[, lo[, hi]])
相当于bisectLeft,但使用的是此bisector的关联comparator。
bisector.right(array, x[, lo[, hi]])
相当于bisectRight,但使用的是此bisector的关联comparator。
d3.ascending(a, b)
如果a小于b,返回-1;如果a大于b,则返回1;如果a等于b,则返回0。这是自然顺序的比较函数,可以结合内置的array.sort方法一同使用对元素进行升序操作,其实现如下:
function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
}
注意:如果没有为内置的sort方法指定comparator,则默认顺序为词典(按字母顺序)顺序,不是自然顺序!当对数字数组进行排序时可能会产生令人吃惊的行为。
var a = 5;
var b = 7;
d3.ascending(a, b); // -1
d3.descending(a, b)
如果a大于b,返回-1;如果a小于b,则返回1;如果a等于b,则返回0。这是自然顺序的比较函数,可以结合内置的array.sort方法一同使用对元素进行降序操作,其实现如下:
function descending(a, b) {
return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
}
注意:如果没有为内置的sort方法指定comparator,则默认顺序为词典(按字母顺序),不是自然顺序!当对数字数组进行排序时可能会产生令人吃惊的行为。
var a = 5;
var b = 7;
d3.ascending(a, b); // 1
Transformations
用于转换数组或生成新数组的方法。
d3.cross(a, b[, reducer])
返回两个数组a和b的Cartesian product(笛卡尔乘积),对于给定数组a中的每个元素i和给定数组b中的每个元素j,依次调用给定的reducer函数并传入元素i和元素j。如果不指定reducer,则默认为一个函数,为每对元素创建一个仅有两个元素的数组:
function pair(a, b) {
return [a, b];
}
例如:
d3.cross([1, 2], ["x", "y"]); // returns [[1, "x"], [1, "y"], [2, "x"], [2, "y"]]
d3.cross([1, 2], ["x", "y"], (a, b) => a + b); // returns ["1x", "1y", "2x", "2y"]
d3.merge(arrays)
将给定的arrays合并为单个数组。此方法类似于内置的concat方法;唯一不同的是,当你有多维数组时它更易使用。
d3.merge([[1], [2, 3]]); // returns [1, 2, 3]
d3.pairs(array[, reducer])
对于给定array中的每对相邻元素,依次调用给定的reducer函数并传入元素i和i-1。如果不reducer,则默认为一个函数,为每对元素创建一个仅有两个元素的数组:
function pair(a, b) {
return [a, b];
}
例如:
d3.pairs([1, 2, 3, 4]); // returns [[1, 2], [2, 3], [3, 4]]
d3.pairs([1, 2, 3, 4], (a, b) => b - a); // returns [1, 1, 1];
如果给定array的元素少于两个,则返回空数组。
d3.permute(array, indexes)
使用给定的indexes数组返回给定array的换位数组。返回的数组包含array中与indexes数组中每个索引相对应的元素。例如:permute(["a", "b", "c"], [1, 2, 0])返回[“B”、“C”、“A”]。无论indexes数组的长度与array的长度是否相等或indexes中有重复、遗漏都是可接受的。
此方法还可以用来从一个对象中提取值组成数组。根据键名按顺序从nested selections(嵌套选集)中提取值对于生成数据数组非常有用。例如:
var object = {yield: 27, variety: "Manchuria", year: 1931, site: "University Farm"},
fields = ["site", "variety", "yield"];
d3.permute(object, fields); // returns ["University Farm", "Manchuria", 27]
d3.shuffle(array[, lo[, hi]])
用Fisher–Yates shuffle算法打乱给定array的顺序。
d3.ticks(start, stop, count)
返回一个近似count+1的数组,数组中的值在start和stop(包含)之间是等间距的、舍入良好的。每个值都是十的幂乘以1,2或5。另请参阅 d3.tickIncrement,d3.tickStep和linear.ticks。
d3.tickIncrement(start, stop, count)
d3.tickStep(start, stop, count)
d3.range([start, ]stop[, step])
返回一个由arithmetic progression(等差级数)组成的数组,类似于Python中的range方法。此方法通常用于迭代一些列均匀分布的数组,如数组的索引或线性比例尺的刻度。(另请参阅d3.ticks。)
如果step被省略,默认为1。如果start被省略,默认为0。stop不包含在结果之中。如果step为正数,则最后一个元素为最大的start+i*step,且小于stop;如果step为负数,则最后一个元素为最小的start+i*step,且大于stop。如果返回的数组包含无穷值,则会返回一个空的range。
参数可以不为整数,但如果都是整数,结果更可预测。返回的数组中的值定义为start+i*step,i为0-1之间的整数减去返回数组中元素的总数。例如:
d3.range(0, 1, 0.2) // [0, 0.2, 0.4, 0.6000000000000001, 0.8]
这种意外行为归结于IEEE 754双精度浮点数,是它定义了0.2*3=0.6000000000000001。可以使用d3-format进行格式化。另请参阅d3-scale中的linear.tickFormat。
同样如果需要返回指定长度的数组,可以对整形range使用array.map。例如:
d3.range(0, 1, 1 / 49); // BAD: returns 50 elements!
d3.range(49).map(function(d) { return d / 49; }); // GOOD: returns 49 elements.
d3.transpose(matrix)
d3.zip(arrays…)
返回一个多维数组,其中第i个数组由每个参数arrays的第i个元素组成。返回的数组长度为参数arrays中长度最短的一个,如果arrays只有一个数组,则返回的数组仅有一个数组元素。如果没有参数,则返回的数组为空。
d3.zip([1, 2], [3, 4]); // returns [[1, 3], [2, 4]]
Histograms
直方图中把许多离散样本分成一部分连续的、无重叠的区间。它们经常被用来可视化数值数据的分布。
d3.histogram()
使用默认配置构造一个新的直方图生成器。
histogram(data)
为给定的data样本数组计算直方图。返回一个bins数组,其中每个bin是一个由输入data中相关元素组成的数组。因此,bin的length
为该bin中元素的数量。每个bin有两个附加属性:
x0
- bin的下边界(包含)x1
- bin的上边界(不包含,除非是最后一个bin)
histogram.value([value])
如果指定了value,则设置value accessor为指定的函数或常量,并返回该直方图生成器。如果不指定value,则返回当前的value accessor,默认为一个标识函数。
当一个直方图生成后,将对输入数据数组的每个元素调用value accessor,并将元素d
,索引i
和数组data
作为参数传入。默认的value accessor假定输入的数据是可排序的(可比较的),如数字或日期。如果你的数据不具备该项条件,那你应该为你的数据指定一个accessor,以返回给定数据相应的可排序值。
这类似于在调用直方图生成器之前将数据映射到values,但有利于输入数据与返回的bins保持关联,从而更容易访问数据的其他字段。
histogram.domain([domain])
如果指定了domain,则设置domain accessor为指定的函数或常量,并返回该直方图生成器。如果不指定domain,则返回当前的domain accessor,默认为extent。histogram domain定义为一个数组array[minx,max],其中min为最小可观察值,max为最大可观察值;两个值都是包含的。当直方图生成后,任何处于此domain外的值都会被忽略。
例如,如果你将直方图与一个linear scalex
一起使用,你可以这样写:
var histogram = d3.histogram()
.domain(x.domain())
.thresholds(x.ticks(20));
然后你可以像这样计算一个数字数组的bins:
var bins = histogram(numbers);
注意:domain accessor是作用于values数组的实例上,不是输入的数据数组。
histogram.thresholds([count])
histogram.thresholds([thresholds])
如果指定thresholds(阈值),则设置threshold generator为指定的函数或常量,并返回该直方图生成器。如果不指定threshold,则返回当前的threshold generator,默认通过Sturges' formula实现(因此默认情况下,直方图的值必须是数字!)。阈值定义为value数组[x0,x1...],任何小于X0的值都将放入第一个bin中;任何大于或等于x0但小于X1的值都将放在第二个bin中,以此类推。因此生成的直方图会有threshold.length+1个bin。另请参阅histogram thresholds。
任何domain以外的阈值都会被忽略。第一个bin.x0总是等于最小domain值,最后一个bin.x1总是等于最大domain值。
如果指定的是count而非threshold,则domain会被均匀的划分为大约count个bin;另请参阅ticks。
Histogram Thresholds
这些函数通常不直接使用,而是传入histogram.thresholds中。你也可以实现自己的threshold generator,提供三个参数:从数据源采集的input values数组,表示min和max的observable domain。generator会返回可枚举的thresholds或bin的count;在后一种情况下,domain会被均匀的划分为大约count个bin;另请参阅ticks。
d3.thresholdFreedmanDiaconis(values, min, max)
根据Freedman–Diaconis规则返回bin的数量,输入的values必须是数字。
d3.thresholdScott(values, min, max)
根据Scott’s normal reference规则返回bin的数量,输入的values必须是数字。
d3.thresholdSturges(values)
根据Sturges’ formula返回bin的数量,输入的values必须是数字。