Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Makerpol/DCAPI

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

20 Commits

Repository files navigation

DC学习

dc.js是一个以d3.js为基础的数据可视化工具,结合crossfilter.js数据处理,让可视化围绕着数据变化而变化。因此要想学dc.js,必须先学习d3.jscrossfilter.js这两个库。

d3.js已经存在中文API翻译,D3v4版API请参照D3-V4-API-CN。 下面开始crossfilter的API翻译以及学习,我会一边翻译,一边学习检验,尽量做到接近作者的以数据为核心的可视化思想。

Crossfilter API Reference

crossfilter 表示多维数组集

# crossfilter([records])

构建新的多维数组集。记录records被指定,添加指定的记录records。 记录records可以是任意的数组,JavaScript对象或者基础数据。如例:

var payments = crossfilter([
 {date: "2011-11-14T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
 {date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
 {date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
 {date: "2011-11-14T16:30:43Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T16:48:46Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T16:53:41Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "cash"},
 {date: "2011-11-14T16:58:03Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T17:07:21Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T17:22:59Z", quantity: 2, total: 90, tip: 0, type: "tab"},
 {date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0, type: "cash"},
 {date: "2011-11-14T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "visa"}
]);

# crossfilter.add(records)

添加指定的记录records到多维数组集crossfilter。

# crossfilter.remove()

从多维数组集中删除所有当前过滤器匹配的记录records。

# crossfilter.size()

返回记录records的数量在多维数组集,独立的任何过滤器中。例如,已经添加单一批次的 记录到多维数据集中,这个方法将返回records.length。

# crossfilter.groupAll()

一个便捷的功能对所有的记录进行分组和减少为单一值。 注意:这个groupAll观察所有的过滤器,和dimension的groupAll不一样。

Dimension

# crossfilter.dimension(value)

使用指定的值访问器函数构造一个新的dimension。这个函数必须返回自然有序的值,即: 正确的行为关于javascript的<, <=>,>=运算符。 这通常意味着基础数据:booleans,数字或者字符串; 然而: 可以重写object.valueOf来保证这个值和给定的对象值相似,如日期。

特别是,注意nullundefined是不支持的。此外,混合类型应该采用,例如:字符串和数字。 如果字符串和数字混合,那么字符串将会强制转换成数字,因此字符串必须可以强制转换成数字,否则就会导致NaN。 例:

var paymentsByTotal = payments.dimension(function(d) { return d.total; });

给定的dimension访问器函数返回的值必须是确定的,并且对于crossfilter的存在永远不变。 性能说明:在内部,缓存给定的dimension的值。因此,如果 dimension值是从其他属性派生的, 没有必要在crossfilter以外派生值。只有当records添加到crossfilter中时才调用值函数。

dimension一旦创建就会绑定到crossfilter。创建超过8个dimension和超过16个dimension 会带来额外的开销。目前不支持一次超过32个dimension。但是可以用dimension.dispose 布置dimension来给新的dimension腾出空间。dimension的状态,记录关联的特定dimension的过滤器,如果真有的话。初期,如果dimension没有指定过滤器:所有的records都会被选中。由于创建dimension比较占用资源,因此应该谨慎保留对创建的任何dimension的引用。

# dimension.filter(value)

过滤records,使dimension值和value匹配,然后返回这个dimension。

这个被指定的value如果是null,这种情况下此方法相当于filterAll; 这个value如果是数组,这种情况下此方法相当于filterRange; 这个value如果是函数,这种情况下此方法相当于filterFunction; 除此之外,此方法相当于filterExact

例:

paymentsByTotal.filter([100, 200]); // 选取总额在100到200之间的付款
paymentsByTotal.filter(120); // 选取总额等于120的付款
paymentsByTotal.filter(function(d) { return d % 2; }); // 选取总额是奇数的付款
paymentsByTotal.filter(null); // 选取所有的付款

如果调用过滤器将会替换现有的过滤器,如果dimension有的话

# dimension.filterExact(value)

过滤records,使dimension值和value匹配,然后返回这个dimension。 例:

paymentsByTotal.filterExact(120); // 选取总额等于120的付款

注意使用排序运算符<, <=>,>=进行精确比较。例如,如果传递的值是null, 这相当于0; 过滤不要用=====运算符。

如果调用过滤器将会替换现有的过滤器,如果dimension有的话

# dimension.filterRange(range)

过滤records,使dimension值大于等于range[0],小于range[1],返回这个dimension。 例:

paymentsByTotal.filterRange([100, 200]); // 选取总额在100到200之间的付款

# dimension.filterFunction(function)

过滤records,被调用时使用指定的函数返回dimension值的真值,并返回dimension。 例:

paymentsByTotal.filterFunction(function(d) { return d % 2; }); // // 选取总额是奇数的付款

这可以用于实现联合过滤器,例如:

// 选取总额在0到10或者20到30之间的付款
paymentsByTotal.filterFunction(function(d) { return 0 <= d && d < 10 || 20 <= d && d < 30; });

# dimension.filterAll()

清除任何dimension的过滤器,选取所有的records并返回dimension。 例:

paymentsByTotal.filterAll(); // 选取所有的付款

# dimension.top(k)

返回一个包含前k个records的数组,根据此dimension的自然顺序。被返回的数组是按照降序的自然顺序进行排列。这个方法和crossfilter当前的过滤器相交,只返回满足所有能动的过滤器(包括此维度的过滤器)的records。 例:

var topPayments = paymentsByTotal.top(4); // the top four payments, by total
topPayments[0]; // the biggest payment
topPayments[1]; // the second-biggest payment
// etc.

如果根据crossfilter所有的过滤器选择的records比k少,那就返回一个少于k的数组。 例:

var allPayments = paymentsByTotal.top(Infinity); //返回所有的

# dimension.bottom(k)

返回一个包含后k个records的数组,根据此dimension的自然顺序。被返回的数组是按照升序的自然顺序进行排列。这个方法和crossfilter当前的过滤器相交,只返回满足所有能动的过滤器(包括此维度的过滤器)的records。 例:

var bottomPayments = paymentsByTotal.bottom(4); // the bottom four payments, by total
bottomPayments[0]; // the smallest payment
bottomPayments[1]; // the second-smallest payment
// etc.

# dimension.dispose()

删除这个dimension(包括它的groups)从crossfilter。这为添加到这个crossfilter其他的dimension释放了空间。

Group (Map-Reduce)

# dimension.group([groupValue])

为给定的dimension构造一个新的群组,根据指定的groupValue函数,采取dimension的值作为输入值,并返回相应的四舍五入值。这个groupValue是可选的;如果不指定,则默认为恒等函数。类似的值函数,groupValue必须返回自然有序的值;此外,这种顺序必须符合这个dimension的值函数。 例:

var paymentGroupsByTotal = paymentsByTotal.group(function(total) { return Math.floor(total / 100); });

默认情况下,这个group的reduce函数将计算每个组的记录数。此外,这个groups将按照记录数排序。

注意:这个分组和crossfire当前的过滤器相交,除了相关联的dimension的过滤器。因此,group方法仅考虑满足除dimension的过滤器之外的每个过滤器的记录。所以,如果付款的ceossfilter是按照type和total过滤,则总额的group只按照type观察过滤器。

# group.size()

返回group中不同值的数量,无关任何过滤器;基础数据。

# group.reduce(add, remove, initial)

指定分组的reduce函数,并返回这个group。默认的行为,通过count进行缩减。 例:

//p是初始化函数返回的对象,v是当前数据
function reduceAdd(p, v) {
 return p + 1;
}
function reduceRemove(p, v) {
 return p - 1;
}
function reduceInitial() {
 return 0;
}

为了缩减total的总数(计算total的总和),你可以修改add函数和remove函数,如下实施:

function reduceAdd(p, v) {
 return p + v.total;
}
function reduceRemove(p, v) {
 return p - v.total;
}

除了add函数以外,remove函数也是需要的,因为group的缩减是逐渐地随着记录被过滤而更新的;在一些情况下,需要从先前计算的group reduction中删除记录。使用许多不同的属性,你可以使用javascript闭包创建add和remove函数

# group.reduceCount()

一个便捷的方法为了统计记录数量的reduce函数,返回这个group。

# group.reduceSum(value)

一个便捷的方法使用指定的value访问器计算记录总和的reduce函数,返回这个group。 例:

//按照付款类型,计算付款总额,相同类型的付款值累加
var paymentsByType = payments.dimension(function(d) { return d.type; }),
 paymentVolumeByType = paymentsByType.group().reduceSum(function(d) { return d.total; }),
 topTypes = paymentVolumeByType.top(1);
topTypes[0].key; // the top payment type (e.g., "tab")
topTypes[0].value; // the payment volume for that type (e.g., 920)

# group.order(orderValue)

指定orderValue计算前K个组。默认的order函数是恒等函数,假定reduction值是自然顺序(如简单的计数和款项)。 例:(//TODO 理解不能 - - !)

function reduceAdd(p, v) {
 ++p.count;
 p.total += v.total;
 return p;
}
function reduceRemove(p, v) {
 --p.count;
 p.total -= v.total;
 return p;
}
function reduceInitial() {
 return {count: 0, total: 0};
}
function orderValue(p) {
 return p.total;
}
var topTotals = paymentVolumeByType.reduce(reduceAdd, reduceRemove, reduceInitial).order(orderValue).top(2);
topTotals[0].key; // payment type with highest total (e.g., "tab")
topTotals[0].value; // reduced value for that type (e.g., {count:8, total:920})

这种技术同样可以计算每个组中特殊值的个数,把计数每一个组缩减的值存储为map,当计数到达零时删除这个map。

# group.orderNatural()

使用自然顺序缩减值的便捷方法。返回这个分组。

# group.top(k)

返回一个包含前k个组的新数组,根据被关联缩减值的组顺序。被返回的数组是按照缩减(统计会不会更容易理解?)值的降序排列。 例:

//检索付款类型数量最多的一个
var paymentsByType = payments.dimension(function(d) { return d.type; }),
 paymentCountByType = paymentsByType.group(),
 topTypes = paymentCountByType.top(1);
topTypes[0].key; // the top payment type (e.g., "tab")
topTypes[0].value; // the count of payments of that type (e.g., 8)

通过crossfilter的过滤器如果group少于k个,就返回一个少于k的数组。如果有一个少于k的非空组,这个方法也有可能返回空的组(零个被选定的记录)。

# group.all()

返回包含所有的组的数组,按照key的升序排列。就像top,被返回的对象包含keyvalue两个属性。被返回的数组也有可能包含空的组:group缩减初始化函数返回的值。 例:

//通过类型计数付款
var types = paymentCountByType.all();

这个方法比'top(Infinity)'更快,因为整个数组原样被返回,而不是选择新数组和排序。不要修改被返回的数组!

# group.dispose()

从dimension中删除group。当新的过滤器应用于crossfilter时这个组将不再更新,如果他没有其他引用,则可能被垃圾回收。

Group All(Reduce)

# dimension.groupAll()

将所有的记录分组到一个简单的组中的便捷函数。被返回的对象相当于一个标准的grouping,除了没有toporder方法。相反,使用value检索符合所有records的缩减值。

# groupAll.reduce(add, remove, initial)

相当于reduce

# groupAll.value()

相当于all()[0].value

Extras

正在实际检验学习中。

crossfilter有几个额外的东西,你应该会感觉很有用。

# crossfilter.bisect

恒等平分;适用于数字,字符串,日期和自然可比的对象。

# crossfilter.bisect.by(value)

使用指定的value访问器构建一个新的平分器,这个访问器必须返回一个自然有序的值。 例:

//通过属性foo将对象数组对分
var bisectByFoo = crossfilter.bisect.by(function(d) { return d.foo; });

返回的对象也是bisect.right函数。

# bisect(array, value, lo, hi) # bisect.right(array, value, lo, hi)

value翻译成插入值/分隔值更合适?

类似bisect.left,但返回一个插入点,这个值是在array中任意现有输入的value之后(右边)。返回的插入点iarray分成两部分:数组中所有在array.silce(lo,i)范围中的v <= value为左半部分;数组中所有在array.silce(i,hi)范围中的v > value为左半部分;

# bisect.left(array, value, lo, hi)

定位数组arrayvalue的插入点,以保持已有的顺序。参数lohi用来指定应该考虑的数组array的子集。


源码解读心得

  • 一个正整数无符号右移1位,所得结果是其本身的一半(奇数的一半直接取整数部分)
1024>>>1 //512
3>>>1 //1

三种移位运算符

<< 左移运算符,num << 1,相当于num乘以2

>> 右移运算符,num >> 1,相当于num除以2

>>> 无符号右移,忽略符号位,空位都以0补齐


参考: crossfilter API 原文

About

dc.js api学习

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle によって変換されたページ (->オリジナル) /