1 | # Transform 数据转换
|
2 |
|
3 | 一个数据视图(DataSet.View)通过 Transform 来进行数据转换操作,其语法如下:
|
4 |
|
5 | ```javascript
|
6 | dv.transform({
|
7 | type: connectorName,
|
8 | ...otherOptions,
|
9 | });
|
10 | ```
|
11 |
|
12 | 举个例子:
|
13 |
|
14 | ```javascript
|
15 | const testCSV = `Expt,Run,Speed
|
16 | 1,1,850
|
17 | 1,2,740
|
18 | 1,3,900
|
19 | 1,4,1070`;
|
20 |
|
21 | const dv = new DataSet.DataView().source(testCSV, {
|
22 | type: 'csv',
|
23 | });
|
24 | console.log(dv.rows);
|
25 | /*
|
26 | * dv.rows:
|
27 | * [
|
28 | * {Expt: " 1", Run: "1", Speed: "850"}
|
29 | * {Expt: " 1", Run: "2", Speed: "740"}
|
30 | * {Expt: " 1", Run: "3", Speed: "900"}
|
31 | * {Expt: " 1", Run: "4", Speed: "1070"}
|
32 | * ]
|
33 | */
|
34 |
|
35 | dv.transform({
|
36 | type: 'filter',
|
37 | callback(row) {
|
38 | return row.Run !== '1';
|
39 | },
|
40 | });
|
41 | console.log(dv.rows);
|
42 | /*
|
43 | * dv.rows:
|
44 | * [
|
45 | * {Expt: " 1", Run: "2", Speed: "740"}
|
46 | * {Expt: " 1", Run: "3", Speed: "900"}
|
47 | * {Expt: " 1", Run: "4", Speed: "1070"}
|
48 | * ]
|
49 | */
|
50 | ```
|
51 |
|
52 | 上述代码中,数据视图实例 `dv` 使用 `csv` 类型的 Connector 载入了一段 CSV 文本,之后执行 `filter` Transform,过滤了某些数据。
|
53 |
|
54 | 目前 DataSet 支持以下 Transform:
|
55 |
|
56 | ## 静态处理相关
|
57 |
|
58 | ### filter 数据过滤
|
59 |
|
60 | 具体用法见示例:
|
61 |
|
62 | ```javascript
|
63 | import { DataView } from '@antv/data-set';
|
64 |
|
65 | const data = [
|
66 | { year: 1990, sales: 200 },
|
67 | { year: 1992, sales: 100 },
|
68 | { year: 1994, sales: 120 },
|
69 | { year: 1995, sales: 85 },
|
70 | ];
|
71 |
|
72 | const dv = new DataView().source(data);
|
73 | dv.transform({
|
74 | type: 'filter',
|
75 | callback(row) {
|
76 | return row.sales < 100;
|
77 | },
|
78 | });
|
79 |
|
80 | console.log(dv.rows); // [ { year: 1995, sales: 85 } ]
|
81 | ```
|
82 |
|
83 | ### map 数据加工
|
84 |
|
85 | 具体用法见示例:
|
86 |
|
87 | ```javascript
|
88 | const data = [
|
89 | { x: 'a', y: 1 },
|
90 | { x: 'b', y: 11 },
|
91 | { x: 'c', y: 21 },
|
92 | ];
|
93 |
|
94 | const dv = new DataView().source(data);
|
95 | dv.transform({
|
96 | type: 'map',
|
97 | callback(row) {
|
98 | row.z = 'z'; // 为每条记录新添加一个 z 字段
|
99 | return row;
|
100 | },
|
101 | });
|
102 |
|
103 | console.log(dv.rows);
|
104 | /*
|
105 | [
|
106 | { x: 'a', y: 1, z: 'z' },
|
107 | { x: 'b', y: 11, z: 'z' },
|
108 | { x: 'c', y: 21, z: 'z' }
|
109 | ]
|
110 | */
|
111 | ```
|
112 |
|
113 | ### pick 字段过滤
|
114 |
|
115 | 具体用法见示例:
|
116 |
|
117 | ```javascript
|
118 | const data = [
|
119 | { x: 1, y: 11 },
|
120 | { x: 2, y: 12 },
|
121 | { x: 3, y: 13 },
|
122 | { x: 4, y: 14 },
|
123 | { x: 5, y: 15 },
|
124 | ];
|
125 |
|
126 | const dv = new DataView().source(data);
|
127 | dv.transform({
|
128 | type: 'pick',
|
129 | fields: ['x'],
|
130 | });
|
131 |
|
132 | console.log(dv.rows);
|
133 | /*
|
134 | [
|
135 | { x: 1 },
|
136 | { x: 2 },
|
137 | { x: 3 },
|
138 | { x: 4 },
|
139 | { x: 5 }
|
140 | ]
|
141 | */
|
142 | ```
|
143 |
|
144 | ### rename 字段重命名
|
145 |
|
146 | > alias: rename-fields
|
147 |
|
148 | 具体用法见示例:
|
149 |
|
150 | ```javascript
|
151 | const data = [{ a: 1, b: 2 }];
|
152 | const dv = new DataView().source(data);
|
153 | dv.transform({
|
154 | type: 'rename',
|
155 | map: {
|
156 | a: 'x',
|
157 | b: 'y',
|
158 | },
|
159 | });
|
160 |
|
161 | console.log(dv.rows); // [ { x: 1, y: 2 } ]
|
162 | ```
|
163 |
|
164 | ### reverse 逆序排列
|
165 |
|
166 | 具体用法见示例:
|
167 |
|
168 | ```javascript
|
169 | const data = [
|
170 | { x: 1, y: 1 },
|
171 | { x: 2, y: 2 },
|
172 | { x: 3, y: 3 },
|
173 | ];
|
174 | const dv = new DataView().source(data);
|
175 | dv.transform({
|
176 | type: 'reverse',
|
177 | });
|
178 |
|
179 | console.log(dv.rows);
|
180 | /*
|
181 | [
|
182 | { x: 3, y: 3 },
|
183 | { x: 2, y: 2 },
|
184 | { x: 1, y: 1 }
|
185 | ]
|
186 | */
|
187 | ```
|
188 |
|
189 | ### sort 数据排序
|
190 |
|
191 | 具体用法见示例:
|
192 |
|
193 | ```javascript
|
194 | dv.transform({
|
195 | type: 'sort',
|
196 | callback(a, b) {
|
197 | // 排序依据,和原生 js 的排序 callback 一致
|
198 | return a.year - b.year;
|
199 | },
|
200 | });
|
201 | ```
|
202 |
|
203 | ### sort-by 按字段排序
|
204 |
|
205 | > alias: sortBy
|
206 |
|
207 | 具体用法见示例:
|
208 |
|
209 | ```javascript
|
210 | dv.transform({
|
211 | type: 'sort-by',
|
212 | fields: ['year'], // 根据指定的字段集进行排序,与lodash的sortBy行为一致
|
213 | order: 'DESC', // 默认为 ASC,DESC 则为逆序
|
214 | });
|
215 | ```
|
216 |
|
217 | ### subset 获取子集
|
218 |
|
219 | 具体用法见示例:
|
220 |
|
221 | ```javascript
|
222 | dv.transform({
|
223 | type: 'subset',
|
224 | startRowIndex: 1, // 保留行的起始索引
|
225 | endRowIndex: 2, // 保留行的结束索引
|
226 | fields: ['year'], // 保留字段集
|
227 | });
|
228 | ```
|
229 |
|
230 | ### partition 数据分组
|
231 |
|
232 | > alias: group | groups
|
233 |
|
234 | 具体用法见示例:
|
235 |
|
236 | ```javascript
|
237 | dv.transform({
|
238 | type: 'partition',
|
239 | groupBy: ['year'], // 以year字段进行分组
|
240 | orderBy: ['month'], // 以month字段进行排序
|
241 | });
|
242 | ```
|
243 |
|
244 | ## 数据形变 / 数据补全相关
|
245 |
|
246 | ### fill-rows 补全行
|
247 |
|
248 | > alias: fillRows
|
249 |
|
250 | 先按照 `groupBy` 和 `orderBy` 进行分组,如果以分组作为补全依据(`fillBy: 'group'`),那么就对比每个分组,以 `orderBy` 序列字段值最全的分组为标准补全数据行数不足的分组。如果以序列作为补全依据(`fillBy: 'order'`),那么就取所有 `orderBy` 序列字段的组合,为每个分组都补充全量的序列。
|
251 |
|
252 | > 注意!如果原始数据有除 groupBy 和 orderBy 指定的字段以外的字段,那么补充的数据行里会缺失这些字段。这时可以结合 impute Transform 来做字段数据补全。
|
253 |
|
254 | 具体用法见示例:
|
255 |
|
256 | > fillBy: group
|
257 |
|
258 | ```javascript
|
259 | const data = [
|
260 | { a: 0, b: 0 },
|
261 | { a: 0, b: 1 },
|
262 | { a: 0, b: 2 },
|
263 | { a: 1, b: 1 },
|
264 | { a: 1, b: 2 },
|
265 | { a: 1, b: 3 },
|
266 | { a: 2, b: 0 },
|
267 | ];
|
268 | const dv = new DataSet.DataView().source(data).transform({
|
269 | type: 'fill-rows',
|
270 | groupBy: ['a'],
|
271 | orderBy: ['b'],
|
272 | fillBy: 'group', // 默认为 group,可选值:order
|
273 | });
|
274 | console.log(dv.rows);
|
275 | /*
|
276 | * dv.rows 变为:
|
277 | * [
|
278 | * { a: 0, b: 0 }, // 分组1 作为第一个序列字段最全(b)的组,被选为基准
|
279 | * { a: 0, b: 1 },
|
280 | * { a: 0, b: 2 },
|
281 | * { a: 1, b: 1 }, // 分组2 序列字段个数和基准组一致,所以不补充数据
|
282 | * { a: 1, b: 2 },
|
283 | * { a: 1, b: 3 },
|
284 | * { a: 2, b: 0 }, // 分组3 缺省数据,根据基准组进行数据补全
|
285 | * { a: 2, b: 1 }, // 这行数据被补充
|
286 | * { a: 2, b: 2 }, // 这行数据被补充
|
287 | * ]
|
288 | */
|
289 | ```
|
290 |
|
291 | > fillBy: order
|
292 |
|
293 | ```javascript
|
294 | // 使用和上例同样的数据
|
295 | const dv = new DataSet.DataView().source(data).transform({
|
296 | type: 'fill-rows',
|
297 | groupBy: ['a'],
|
298 | orderBy: ['b'],
|
299 | fillBy: 'order', // 默认为 group,可选值:order
|
300 | });
|
301 | console.log(dv.rows);
|
302 | /*
|
303 | * dv.rows 变为:
|
304 | * [
|
305 | * { a: 0, b: 0 }, // 分组1
|
306 | * { a: 0, b: 1 },
|
307 | * { a: 0, b: 2 },
|
308 | * { a: 0, b: 3 }, // 分组1 补充了这行数据,因为全量的序列字段(b)有这个值
|
309 | * { a: 1, b: 0 }, // 分组2 补充了这行数据,因为全量的序列字段(b)有这个值
|
310 | * { a: 1, b: 1 },
|
311 | * { a: 1, b: 2 },
|
312 | * { a: 1, b: 3 },
|
313 | * { a: 2, b: 0 }, // 分组3 缺省数据,根据基准组进行数据补全
|
314 | * { a: 2, b: 1 }, // 这行数据被补充
|
315 | * { a: 2, b: 2 }, // 这行数据被补充
|
316 | * { a: 2, b: 3 }, // 这行数据被补充
|
317 | * ]
|
318 | */
|
319 | ```
|
320 |
|
321 | ### impute 补全列 / 补全字段
|
322 |
|
323 | 根据配置规则为某个字段补全缺失值。
|
324 |
|
325 | 具体用法见示例:
|
326 |
|
327 | ```javascript
|
328 | const data = [
|
329 | { x: 0, y: 1 },
|
330 | { x: 0, y: 2 },
|
331 | { x: 0, y: 3 },
|
332 | { x: 0 },
|
333 | { x: 1, y: 5 },
|
334 | { x: 1, y: 6 },
|
335 | { x: 1, y: 7 },
|
336 | { x: 1 },
|
337 | { x: 1, y: 9 },
|
338 | { x: 2 },
|
339 | ];
|
340 | const dv = new DataSet.DataView().source(data).transform({
|
341 | type: 'impute',
|
342 | field: 'y', // 待补全字段
|
343 | groupBy: ['x'], // 分组字段集(传空则不分组)
|
344 | method: 'max', // 补全字段值时执行的规则
|
345 | });
|
346 | /*
|
347 | dv.rows 变为
|
348 | [
|
349 | { x: 0, y: 1 },
|
350 | { x: 0, y: 2 },
|
351 | { x: 0, y: 3 },
|
352 | { x: 0, y: 3 },
|
353 | { x: 1, y: 5 },
|
354 | { x: 1, y: 6 },
|
355 | { x: 1, y: 7 },
|
356 | { x: 1, y: 7 },
|
357 | { x: 1, y: 9 },
|
358 | { x: 2, y: 9 }
|
359 | ]
|
360 | */
|
361 | ```
|
362 |
|
363 | > 补全字段的规则(method)有常见的统计函数:max, min, median, mean
|
364 |
|
365 | > 还有补充固定值的写法:method 指定为 value,然后 value 指定为填充的常量,譬如
|
366 |
|
367 | ```javascript
|
368 | dv.transform({
|
369 | type: 'impute',
|
370 | field: 'y', // 待补全字段
|
371 | groupBy: ['x'], // 分组字段集(传空则不分组)
|
372 | method: 'value', // 补全常量
|
373 | value: 10, // 补全的常量为10
|
374 | });
|
375 | ```
|
376 |
|
377 | ### fold 字段展开
|
378 |
|
379 | 以指定字段集为 key,展开数据。
|
380 |
|
381 | 具体用法见示例:
|
382 |
|
383 | ```javascript
|
384 | const data = [
|
385 | { country: 'USA', gold: 10, silver: 20 },
|
386 | { country: 'Canada', gold: 7, silver: 26 },
|
387 | ];
|
388 | const dv = ds
|
389 | .createView()
|
390 | .source(data)
|
391 | .transform({
|
392 | type: 'fold',
|
393 | fields: ['gold', 'silver'], // 展开字段集
|
394 | key: 'key', // key字段
|
395 | value: 'value', // value字段
|
396 | retains: ['country'], // 保留字段集,默认为除 fields 以外的所有字段
|
397 | });
|
398 | /*
|
399 | dv.rows 变为
|
400 | [
|
401 | { key: gold, value: 10, country: "USA" },
|
402 | { key: silver, value: 20, country: "USA" },
|
403 | { key: gold, value: 7, country: "Canada" },
|
404 | { key: silver, value: 26, country: "Canada" }
|
405 | ]
|
406 | */
|
407 | ```
|
408 |
|
409 | ## 数据比例(百分比)相关 Transform
|
410 |
|
411 | ### percent 总和百分比
|
412 |
|
413 | 统计某个维度下某个字段的值的和占总和的比例(可以分组)。
|
414 |
|
415 | `field` 是统计发生的字段(求和,求百分比),`dimension` 是统计的维度字段,也就是"每个不同的 `dimension` 下,`field` 值占总和的百分比",`groupBy` 则是分组字段,每一个分组内部独立求百分比(每一个分组内,最后的 `percent` 字段相加之和为 1)。
|
416 |
|
417 | 具体用法见示例:
|
418 |
|
419 | ```javascript
|
420 | dv.transform({
|
421 | type: 'percent',
|
422 | field: 'sold', // 统计销量
|
423 | dimension: 'year', // 每年的占比
|
424 | groupBy: ['category'], // 以不同产品类别为分组,每个分组内部各自统计占比
|
425 | as: 'percent', // 结果存储在 percent 字段
|
426 | });
|
427 | ```
|
428 |
|
429 | ### proportion 行数百分比
|
430 |
|
431 | 统计某个维度下某个字段的数据条数占总条数的比例(可以分组)。和 percent Transform 类似,但统计的是数据条目的占比,而不是数据总和的占比。
|
432 |
|
433 | 具体用法见示例:
|
434 |
|
435 | ```javascript
|
436 | dv.transform({
|
437 | type: 'proportion',
|
438 | dimension: 'year', // 每年的占比
|
439 | groupBy: ['category'], // 以不同产品类别为分组,每个分组内部各自统计占比
|
440 | as: 'proportion', // 结果存储在proportion字段
|
441 | });
|
442 | ```
|
443 |
|
444 | ## 数据统计相关
|
445 |
|
446 | ### aggregate 聚合统计
|
447 |
|
448 | 统计处理,支持并行的多种统计。
|
449 |
|
450 | 具体用法见示例:
|
451 |
|
452 | ```javascript
|
453 | dv.transform({
|
454 | type: 'aggregate', // 别名summary
|
455 | fields: [], // 统计字段集
|
456 | operations: [], // 统计操作集
|
457 | as: [], // 存储字段集
|
458 | groupBy: [], // 分组字段集
|
459 | });
|
460 | ```
|
461 |
|
462 | > 以上 fields/operations/as 这三个数组元素一一对应。“对某个字段 field 进行某种统计操作 operation 结果存储在某个字段上 as。”
|
463 |
|
464 | 支持的 operations: [详见 simple-statistics](https://simplestatistics.org/)。
|
465 |
|
466 | - count
|
467 | - max
|
468 | - min
|
469 | - mean
|
470 | - median
|
471 | - mode
|
472 | - product
|
473 | - standardDeviation
|
474 | - sum
|
475 | - sumSimple
|
476 | - variance
|
477 |
|
478 | ### regression 回归曲线
|
479 |
|
480 | 计算两个字段的回归拟合曲线。
|
481 |
|
482 | 具体用法见示例:
|
483 |
|
484 | ```javascript
|
485 | dv.transform({
|
486 | type: 'regression',
|
487 | method: 'linear', // 回归算法类型
|
488 | fields: ['x', 'y'], // 统计字段
|
489 | bandwidth: 0.1, // 步长
|
490 | extent: [0, 4], // 结果集里,x的数值范围
|
491 | as: ['x', 'y'], // 结果字段
|
492 | });
|
493 | ```
|
494 |
|
495 | 支持的回归算法类型:
|
496 |
|
497 | - linear
|
498 | - exponential
|
499 | - logarithmic
|
500 | - power
|
501 | - polynomial
|
502 |
|
503 | ## 数据分箱相关
|
504 |
|
505 | ### bin.histogram 直方图分箱
|
506 |
|
507 | 单字段
|
508 |
|
509 | > alias: bin.dot
|
510 |
|
511 | 具体用法见示例:
|
512 |
|
513 | ```javascript
|
514 | dv.transform({
|
515 | type: 'bin.histogram',
|
516 | field: 'a', // 对应数轴上的一个点
|
517 | bins: 30, // 分箱个数
|
518 | binWidth: 10, // 分箱步长(会覆盖bins选项)
|
519 | offset: 0, // 分箱偏移量
|
520 | groupBy: [], // 分组(用于层叠直方图)
|
521 | as: ['x', 'count'], // x 为数组,存储了某个分箱的上下限 [x0, x1]
|
522 | });
|
523 | ```
|
524 |
|
525 | ### bin.quantile 分位值分箱
|
526 |
|
527 | 单字段
|
528 |
|
529 | 具体用法见示例:
|
530 |
|
531 | ```javascript
|
532 | dv.transform({
|
533 | type: 'bin.quantile',
|
534 | field: 'y', // 计算分为值的字段
|
535 | as: '_bin', // 保存分为值的数组字段
|
536 | groupBy: [], // 分组
|
537 | fraction: 4, // 可选,默认四分位
|
538 | p: [0.5, 0.3], // 可选,p参数列表,与 fraction 二选一
|
539 | });
|
540 | ```
|
541 |
|
542 | ### bin.hexagon 六边形分箱
|
543 |
|
544 | 双字段
|
545 |
|
546 | > alias: bin.hex | hexbin
|
547 |
|
548 | 具体用法见示例:
|
549 |
|
550 | ```javascript
|
551 | dv.transform({
|
552 | type: 'bin.hexagon',
|
553 | fields: ['a', 'b'], // 对应坐标轴上的一个点
|
554 | bins: [30, 30], // 两个方向上的分箱个数
|
555 | binWidth: [10, 1000], // 两个方向上的分箱步长(会覆盖bins的配置)
|
556 | offset: [0, 0], // 两个方向上的分箱偏移量
|
557 | sizeByCount: false, // 是否根据分箱个数调整分箱大小(六边形的半径)
|
558 | as: ['x', 'y', 'count'], // 这个点落在的六边形的顶点坐标集,以及每个分箱内的数据条数
|
559 | // x: [ x0, x1, x2, x3, x4, x5 ], y: [ y0, y1, y2, y3, y4, y5 ]
|
560 | // count: Number
|
561 | });
|
562 | /*
|
563 | * 顶点顺序:
|
564 | * 3
|
565 | * 4 2
|
566 | *
|
567 | * 5 1
|
568 | * 0
|
569 | */
|
570 | ```
|
571 |
|
572 | ### bin.rectangle 矩形分箱
|
573 |
|
574 | 双字段
|
575 |
|
576 | > alias: bin.rect
|
577 |
|
578 | 具体用法见示例:
|
579 |
|
580 | ```javascript
|
581 | dv.transform({
|
582 | type: 'bin.rectangle',
|
583 | fields: ['a', 'b'], // 对应坐标轴上的一个点
|
584 | bins: [30, 30], // 两个方向上的分箱个数
|
585 | binWidth: [10, 10], // 两个方向上的分箱步长(会覆盖bins配置)
|
586 | offset: [0, 0], // 两个方向上的分箱偏移量
|
587 | sizeByCount: false, // 是否根据分箱个数调整分箱大小
|
588 | as: ['x', 'y', 'count'], // 这个点落在的六边形的顶点坐标集
|
589 | // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
|
590 | // count: Number
|
591 | });
|
592 | /*
|
593 | * 顶点顺序:
|
594 | * 3 - 2
|
595 | * | |
|
596 | * 0 - 1
|
597 | */
|
598 | ```
|
599 |
|
600 | ## 核函数相关
|
601 |
|
602 | ### kernel-smooth.regression 核函数概率密度回归
|
603 |
|
604 | 用于画核函数概率密度回归曲线,支持单字段或者双字段。
|
605 |
|
606 | 具体用法见示例:
|
607 |
|
608 | ```javascript
|
609 | dv.transform({
|
610 | type: 'kernel-smooth.regression',
|
611 | fields: ['x', 'y'], // 必填,1 或 2 字段
|
612 | method: 'gaussian', // 采用的核函数类型。也可以指定为自定义的函数
|
613 | extent: [min(x), max(x)], // 数值范围,默认为 x 字段的数值范围
|
614 | bandwidth: 0.4, // 步长,默认采用 silverman 的算法计算
|
615 | as: ['x', 'y'], // 结果字段,单字段时,y 为 x 值对应的概率
|
616 | });
|
617 | ```
|
618 |
|
619 | 支持的核函数类型:
|
620 |
|
621 | - cosine
|
622 | - epanechnikov
|
623 | - gaussian (default)
|
624 | - quartic
|
625 | - triangular
|
626 | - tricube
|
627 | - triweight
|
628 | - uniform
|
629 |
|
630 | ### kernel-smooth.density 核函数概率密度分布
|
631 |
|
632 | 用于画核函数概率密度分布热力图,双字段。
|
633 |
|
634 | 具体用法见示例:
|
635 |
|
636 | ```javascript
|
637 | dv.transform({
|
638 | type: 'kernel-smooth.density',
|
639 | fields: ['x', 'y'], // 必填
|
640 | method: 'gaussian', // 采用的核函数类型。也可以指定为自定义的函数
|
641 | extent: [
|
642 | [min(x), max(x)],
|
643 | [min(y), max(y)],
|
644 | ], // 数值范围,默认为 x 以及 y 字段各自的数值范围
|
645 | bandwidth: 0.4, // 步长,默认采用 silverman 的算法计算
|
646 | as: ['x', 'y'], // 结果字段,单字段时,y 为 x 值对应的概率
|
647 | });
|
648 | ```
|
649 |
|
650 | > silverman 提出的 bandwidth 计算算法: [paper](https://ned.ipac.caltech.edu/level5/March02/Silverman/paper.pdf)
|
651 |
|
652 | 支持的核函数类型同上
|
653 |
|
654 | ## 树相关
|
655 |
|
656 | ### hierarchy.treemap 树形图
|
657 |
|
658 | > alias: treemap
|
659 |
|
660 | 根据树形数据生成树形图 Treemap 布局。
|
661 |
|
662 | 具体用法见示例:
|
663 |
|
664 | ```javascript
|
665 | dv.transform({
|
666 | type: 'hierarchy.treemap',
|
667 | field: 'value',
|
668 | tile: 'treemapSquarify', // 布局类型
|
669 | size: [1, 1], // width, height
|
670 | round: false,
|
671 | // ratio: 1.618033988749895, // golden ratio
|
672 | padding: 0, // 各种 padding 配置
|
673 | paddingInner: 0,
|
674 | paddingOuter: 0,
|
675 | paddingTop: 0,
|
676 | paddingRight: 0,
|
677 | paddingBottom: 0,
|
678 | paddingLeft: 0,
|
679 | as: ['x', 'y'], // 矩形的顶点集
|
680 | // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
|
681 | });
|
682 | ```
|
683 |
|
684 | 支持的布局类型:
|
685 |
|
686 | - treemapBinary
|
687 | - treemapDice
|
688 | - treemapSlice
|
689 | - treemapSliceDice
|
690 | - treemapSquarify
|
691 | - treemapResquarify
|
692 |
|
693 | ### hierarchy.partition 相邻层次图
|
694 |
|
695 | > alias: adjacency
|
696 |
|
697 | 根据树形数据生成相邻层次图 Adjacency Diagram 布局,可以通过坐标变换变形为 Sunburst 图。
|
698 |
|
699 | 具体用法见示例:
|
700 |
|
701 | ```javascript
|
702 | dv.transform({
|
703 | type: 'hierarchy.partition',
|
704 | field: 'value',
|
705 | size: [1, 1], // width, height
|
706 | round: false,
|
707 | // ratio: 1.618033988749895, // golden ratio
|
708 | padding: 0, // 各种 padding 配置
|
709 | as: ['x', 'y'], // 矩形的顶点集
|
710 | // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
|
711 | });
|
712 | ```
|
713 |
|
714 | ## 图相关
|
715 |
|
716 | ### diagram.arc 弧长链接图
|
717 |
|
718 | 弧长链接图(Arc Diagram)可以变形为和弦图(Chord Diagram)。
|
719 |
|
720 | > alias: arc
|
721 |
|
722 | 具体用法见示例:
|
723 |
|
724 | ```javascript
|
725 | dv.transform({
|
726 | type: 'diagram.arc',
|
727 | y: 0,
|
728 | thickness: 0.05, // 节点高度,区间 (0, 1)
|
729 | weight: false, // 是否带权重,无权重为弧长链接图,带权重为和弦图
|
730 | marginRatio: 0.1, // 空隙比例,区间[0, 1)
|
731 | id: (node) => node.id, // 获取节点id
|
732 | source: (edge) => edge.source, // 获取边起始点id
|
733 | target: (edge) => edge.target, // 获取边结束点id
|
734 | sourceWeight: (edge) => edge.value, // 获取边起始点权重
|
735 | targetWeight: (edge) => edge.value1, // 获取边结束点权重
|
736 | sortBy: null, // 排序,可以按照id,权重('weight')或者边数量('frequency')排序,也可以自定排序函数
|
737 | });
|
738 | ```
|
739 |
|
740 | > 注意!这个 Transform 做完之后,有两部分数据(顶点和边数据),G2 在使用是不能直接通过 chart.source(dv) 来导入数据,只能分别导入顶点和边集合,例如:
|
741 |
|
742 | ```javascript
|
743 | const nodeView = chart.view();
|
744 | nodeView.source(dv.nodes);
|
745 |
|
746 | const edgeView = chart.view();
|
747 | edgeView.source(dv.edges);
|
748 | ```
|
749 |
|
750 | ### diagram.sankey 桑基图
|
751 |
|
752 | > alias: sankey
|
753 |
|
754 | 具体用法见示例:
|
755 |
|
756 | ```javascript
|
757 | dv.transform({
|
758 | type: 'diagram.sankey',
|
759 | source: (edge) => edge.source, // 边起点id
|
760 | target: (edge) => edge.target, // 边终点id
|
761 | nodeAlign: 'sankeyJustify', // sankeyLeft / sankeyRight / sankeyCenter
|
762 | nodeWidth: 0.02, // 节点宽,范围:(0, 1)
|
763 | nodePadding: 0.02, // 节点上下间距,范围:(0, 1)
|
764 | sort: undefined | null | ((a: any, b: any) => number); // 同列节点排序 undefined 默认值 在每次迭代过程中按宽度递增、null 按照数据排序 不重新排序、function 根据指定函数进行排序,并在初始化的时候排序一次
|
765 | });
|
766 | ```
|
767 |
|
768 | > 注意!这个 Transform 做完后同样需要注意上述 arc transform 一样的数据导入问题
|
769 |
|
770 | ### diagram.voronoi
|
771 |
|
772 | voronoi 图
|
773 |
|
774 | > alias: voronoi
|
775 |
|
776 | 具体用法见示例:
|
777 |
|
778 | ```javascript
|
779 | dv.transform({
|
780 | type: 'diagram.voronoi',
|
781 | fields: ['field0', 'field1'], // 对应坐标轴上的一个点
|
782 | extend: [
|
783 | [x0, y0],
|
784 | [x1, y1],
|
785 | ], // 范围
|
786 | size: [width, height], // 范围
|
787 | as: ['x', 'y'], // 每个点包围多边形的顶点集
|
788 | // x: [ x0, x1, x2, ... ], y: [ y0, y1, y2, ... ]
|
789 | });
|
790 | ```
|
791 |
|
792 | ## Geo 地理数据相关
|
793 |
|
794 | ### geo.projection 地理映射
|
795 |
|
796 | 具体用法见示例:
|
797 |
|
798 | ```javascript
|
799 | dv.transform({
|
800 | type: 'geo.projection',
|
801 | projection: 'geoAiry', // 指定映射类型
|
802 | as: ['x', 'y', 'centroid_x', 'centroid_y'], // x,y是对应多边形的顶点集
|
803 | // centroid_x是中心点的x坐标
|
804 | // centroid_y是中心点y坐标
|
805 | });
|
806 | ```
|
807 |
|
808 | ### geo.centroid 由地名获取地理位置点
|
809 |
|
810 | 具体用法见示例:
|
811 |
|
812 | ```javascript
|
813 | dv.transform({
|
814 | type: 'geo.centroid',
|
815 | field: 'name', // 标注地名的字段
|
816 | geoDataView: geoDataView, // 使用的geo数据来源,可以是DataView实例,也可以是DataView实例的name
|
817 | as: ['_centroid_x', '_centroid_y'], // _centroid_x是中心点的x坐标
|
818 | // _centroid_y是中心点y坐标
|
819 | });
|
820 | ```
|
821 |
|
822 | ### geo.region 由地名获取地理位置区域
|
823 |
|
824 | 具体用法见示例:
|
825 |
|
826 | ```javascript
|
827 | dv.transform({
|
828 | type: 'geo.region',
|
829 | field: 'name', // 标注地名的字段
|
830 | geoDataView: geoDataView, // 使用的geo数据来源,可以是DataView实例,也可以是DataView实例的name
|
831 | as: ['_x', '_y'], // 多边形的顶点集
|
832 | // _x: [ x0, x1, x2, ... ], _y: [ y0, y1, y2, ... ]
|
833 | });
|
834 | ```
|
835 |
|
836 | ## 其他
|
837 |
|
838 | ### tag-cloud 词云布局
|
839 |
|
840 | > alias: word-cloud
|
841 |
|
842 | 具体用法见示例:
|
843 |
|
844 | ```javascript
|
845 | dv.transform({
|
846 | type: 'tag-cloud',
|
847 | fields: ['text', 'value'], // 参与标签云layout的字段集(前者为文本内容,后者为权重值)
|
848 | font: 'serif', // 标签字体
|
849 | size: [500, 500], // 画布size,[ width, height ]
|
850 | padding: 0,
|
851 | spiral: 'archimedean', // 标签螺旋排布规律函数 'archimedean' || 'rectangular' || {function}
|
852 | fontSize(d) {
|
853 | return d.value;
|
854 | }, // 计算标签字体大小的回调函数,d为一行数据
|
855 | timeInterval: Infinity, // 最大迭代时间,默认为无限大
|
856 | imageMask: { Image }, // Image的实例,必须是 loaded 状态
|
857 | });
|
858 | ```
|
859 |
|
860 | > 带图片形状的词云布局实例
|
861 |
|
862 | ```javascript
|
863 | const imageMask = new Image();
|
864 | imageMask.crossOrigin = '';
|
865 | imageMask.src = 'https://zos.alipayobjects.com/rmsportal/EEFqYWuloqIHRnh.jpg';
|
866 | imageMask.onload = () => {
|
867 | dv.transform({
|
868 | type: 'tag-cloud',
|
869 | imageMask,
|
870 | });
|
871 | };
|
872 | ```
|