Transform 数据转换

    举个例子:

    1. const testCSV = `Expt,Run,Speed
    2. 1,1,850
    3. 1,2,740
    4. 1,3,900
    5. 1,4,1070`;
    6.  
    7. const dv = new DataSet.View().source(testCSV, {
    8. type: 'csv'
    9. });
    10. console.log(dv.rows);
    11. /*
    12. * dv.rows:
    13. * [
    14. * {Expt: " 1", Run: "1", Speed: "850"}
    15. * {Expt: " 1", Run: "2", Speed: "740"}
    16. * {Expt: " 1", Run: "3", Speed: "900"}
    17. * {Expt: " 1", Run: "4", Speed: "1070"}
    18. * ]
    19. */
    20.  
    21. dv.transform({
    22. type: 'filter',
    23. callback(row) {
    24. return row.Run !== "1";
    25. }
    26. });
    27. console.log(dv.rows);
    28. /*
    29. * dv.rows:
    30. * [
    31. * {Expt: " 1", Run: "2", Speed: "740"}
    32. * {Expt: " 1", Run: "3", Speed: "900"}
    33. * {Expt: " 1", Run: "4", Speed: "1070"}
    34. * ]
    35. */
    36.  

    上述代码中,数据视图实例 使用 csv 类型的 Connector 载入了一段 CSV 文本,之后执行 filter Transform,过滤了某些数据。

    目前 DataSet 支持以下 Transform:

    具体用法见示例:

    1. dv.transform({
    2. type: 'filter',
    3. callback(row) { // 判断某一行是否保留,默认返回true
    4. return row.year > 1998;
    5. }
    6. });

    map 数据加工

    具体用法见示例:

    1. dv.transform({
    2. type: 'map',
    3. callback(row) { // 加工数据后返回新的一行,默认返回行数据本身
    4. row.newCol = row.xxx + row.yyy;
    5. return row;
    6. }
    7. });

    pick 字段过滤

    具体用法见示例:

    1. dv.transform({
    2. type: 'pick',
    3. fields: [ 'xxx', 'yyy' ] // 决定保留哪些字段,如果不传,则返回所有字段
    4. });

    rename 字段重命名

    具体用法见示例:

    1. dv.transform({
    2. type: 'rename',
    3. map: {
    4. xxx: 'yyy' // row.xxx 会被替换成 row.yyy
    5. }
    6. });

    reverse 逆序排列

    具体用法见示例:

    1. dv.transform({ // 把数据行逆序排列
    2. type: 'reverse',
    3. });

    sort 数据排序

    具体用法见示例:

    1. dv.transform({
    2. type: 'sort',
    3. callback(a, b) { // 排序依据,和原生js的排序callback一致
    4. return a.year - b.year;
    5. }
    6. });

    sort-by 按字段排序

    alias: sortBy

    具体用法见示例:

    1. dv.transform({
    2. type: 'sort-by',
    3. fields: [ 'year' ], // 根据指定的字段集进行排序,与lodash的sortBy行为一致
    4. order: 'DESC' // 默认为 ASC,DESC 则为逆序
    5. })

    subset 获取子集

    具体用法见示例:

    1. dv.transform({
    2. type: 'subset',
    3. startRowIndex: 1, // 保留行的起始索引
    4. endRowIndex: 2, // 保留行的结束索引
    5. fields: [ 'year' ] // 保留字段集
    6. })

    partition 数据分组

    alias: group | groups

    具体用法见示例:

    1. dv.transform({
    2. type: 'partition',
    3. groupBy: [ 'year' ], // 以year字段进行分组
    4. orderBy: [ 'month' ] // 以month字段进行排序
    5. });

    数据形变/数据补全相关

    fill-rows 补全行

    alias: fillRows

    先按照 groupByorderBy 进行分组,如果以分组作为补全依据(),那么就对比每个分组,以 orderBy 序列字段值最全的分组为标准补全数据行数不足的分组。如果以序列作为补全依据(fillBy: 'order'),那么就取所有 orderBy 序列字段的组合,为每个分组都补充全量的序列。

    注意!如果原始数据有除 groupBy 和 orderBy 指定的字段以外的字段,那么补充的数据行里会缺失这些字段。这时可以结合 impute Transform 来做字段数据补全。

    具体用法见示例:

    fillBy: group
    1. const data = [
    2. { a: 0, b: 0 },
    3. { a: 0, b: 1 },
    4. { a: 0, b: 2 },
    5. { a: 1, b: 1 },
    6. { a: 1, b: 2 },
    7. { a: 1, b: 3 },
    8. { a: 2, b: 0 }
    9. ];
    10. const dv = new DataSet.View().source(data)
    11. .transform({
    12. type: 'fill-rows',
    13. groupBy: [ 'a' ],
    14. orderBy: [ 'b' ],
    15. fillBy: 'group' // 默认为 group,可选值:order
    16. });
    17. console.log(dv.rows);
    18. /*
    19. * [
    20. * { a: 0, b: 0 }, // 分组1 作为第一个序列字段最全(b)的组,被选为基准
    21. * { a: 0, b: 1 },
    22. * { a: 0, b: 2 },
    23. * { a: 1, b: 1 }, // 分组2 序列字段个数和基准组一致,所以不补充数据
    24. * { a: 1, b: 2 },
    25. * { a: 1, b: 3 },
    26. * { a: 2, b: 0 }, // 分组3 缺省数据,根据基准组进行数据补全
    27. * { a: 2, b: 1 }, // 这行数据被补充
    28. * { a: 2, b: 2 }, // 这行数据被补充
    29. * ]
    30. */
    fillBy: order

    根据配置规则为某个字段补全缺失值。

    具体用法见示例:

    1. const data = [
    2. { x: 0, y: 1 },
    3. { x: 0, y: 2 },
    4. { x: 0, y: 3 },
    5. { x: 0 },
    6. { x: 1, y: 5 },
    7. { x: 1, y: 6 },
    8. { x: 1, y: 7 },
    9. { x: 1 },
    10. { x: 1, y: 9 },
    11. { x: 2 }
    12. ];
    13. const dv = new DataSet.View().source(data)
    14. .transform({
    15. type: 'impute',
    16. field: 'y', // 待补全字段
    17. groupBy: [ 'x' ], // 分组字段集(传空则不分组)
    18. method: 'max' // 补全字段值时执行的规则
    19. });
    20. /*
    21. dv.rows 变为
    22. [
    23. { x: 0, y: 1 },
    24. { x: 0, y: 2 },
    25. { x: 0, y: 3 },
    26. { x: 0, y: 3 },
    27. { x: 1, y: 5 },
    28. { x: 1, y: 6 },
    29. { x: 1, y: 7 },
    30. { x: 1, y: 7 },
    31. { x: 1, y: 9 },
    32. { x: 2, y: 9 }
    33. ]
    34. */
    补全字段的规则(method)有常见的统计函数:max, min, median, mean
    1. dv.transform({
    2. type: 'impute',
    3. field: 'y', // 待补全字段
    4. groupBy: [ 'x' ], // 分组字段集(传空则不分组)
    5. method: 'value', // 补全常量
    6. value: 10 // 补全的常量为10
    7. });

    fold 字段展开

    以指定字段集为key,展开数据。

    具体用法见示例:

    1. const data = [
    2. { country: "USA", gold: 10, silver: 20 },
    3. { country: "Canada", gold: 7, silver: 26 }
    4. ];
    5. const dv = ds.createView()
    6. .source(data)
    7. .transform({
    8. type: 'fold',
    9. fields: [ 'gold', 'silver' ], // 展开字段集
    10. key: 'key', // key字段
    11. value: 'value', // value字段
    12. retains: [ 'country' ] // 保留字段集,默认为除 fields 以外的所有字段
    13. });
    14. /*
    15. dv.rows 变为
    16. [
    17. { key: gold, value: 10, country: "USA" },
    18. { key: silver, value: 20, country: "USA" },
    19. { key: gold, value: 7, country: "Canada" },
    20. { key: silver, value: 26, country: "Canada" }
    21. ]
    22. */

    数据比例(百分比)相关 Transform

    percent 总和百分比

    统计某个维度下某个字段的值的和占总和的比例(可以分组)。

    具体用法见示例:

    1. dv.transform({
    2. type: 'percent',
    3. field: 'sold', // 统计销量
    4. dimension: 'year', // 每年的占比
    5. groupBy: [ 'category' ], // 以不同产品类别为分组
    6. as: 'percent' // 结果存储在 percent 字段
    7. });

    proportion 行数百分比

    统计某个维度下某个字段的数据条数占总条数的比例(可以分组)。和 percent Transform 类似,但统计的是数据条目的占比,而不是数据总和的占比。

    具体用法见示例:

    1. dv.transform({
    2. type: 'proportion',
    3. field: 'id', // 统计条数
    4. dimension: 'year', // 每年的占比
    5. groupBy: [ 'category' ], // 以不同产品类别为分组
    6. as: 'proportion' // 结果存储在proportion字段
    7. });

    aggregate 聚合统计

    统计处理,支持并行的多种统计。

    具体用法见示例:

    1. dv.transform({
    2. type: 'aggregate', // 别名summary
    3. fields: [], // 统计字段集
    4. operations: [], // 统计操作集
    5. as: [], // 存储字段集
    6. groupBy: [] // 分组字段集
    7. })
    以上fields/operations/as这三个数组元素一一对应。“对某个字段field进行某种统计操作operation结果存储在某个字段上as”

    支持的operations:

    • count
    • max
    • min
    • mean
    • median
    • mode
    • product
    • standardDeviation
    • sum
    • sumSimple
    • variance

      regression 回归曲线

    计算两个字段的回归拟合曲线。

    具体用法见示例:

    1. dv.transform({
    2. type: 'regression',
    3. method: 'linear', // 回归算法类型
    4. fields: [ 'x', 'y' ], // 统计字段
    5. bandwidth: 0.1, // 步长
    6. extent: [ 0, 4 ], // 结果集里,x的数值范围
    7. as: [ 'x', 'y' ] // 结果字段
    8. });

    支持的回归算法类型:

    • linear
    • exponential
    • logarithmic
    • power
    • polynomial

      数据分箱相关

    bin.histogram 直方图分箱

    单字段

    alias: bin.dot

    具体用法见示例:

    1. dv.transform({
    2. type: 'bin.histogram',
    3. field: 'a', // 对应数轴上的一个点
    4. bins: 30, // 分箱个数
    5. binWidth: 10, // 分箱步长(会覆盖bins选项)
    6. offset: 0, // 分箱偏移量
    7. groupBy: [], // 分组(用于层叠直方图)
    8. as: [ 'x', 'count' ], // x 为数组,存储了某个分箱的上下限 [x0, x1]
    9. });

    bin.quantile 分位值分箱

    单字段

    具体用法见示例:

    1. dv.transform({
    2. type: 'bin.quantile',
    3. field: 'y', // 计算分为值的字段
    4. as: '_bin', // 保存分为值的数组字段
    5. groupBy: [], // 分组
    6. fraction: 4, // 可选,默认四分位
    7. p: [ 0.5, 0.3 ] // 可选,p参数列表,与 fraction 二选一
    8. });

    bin.hexagon 六边形分箱

    双字段

    alias: bin.hex | hexbin

    具体用法见示例:

    1. dv.transform({
    2. type: 'bin.hexagon',
    3. fields: [ 'a', 'b' ], // 对应坐标轴上的一个点
    4. bins: [ 30, 30 ], // 两个方向上的分箱个数
    5. binWidth: [ 10, 1000 ], // 两个方向上的分箱步长(会覆盖bins的配置)
    6. offset: [ 0, 0 ], // 两个方向上的分箱偏移量
    7. as: [ 'x', 'y', 'count' ], // 这个点落在的六边形的顶点坐标集,以及每个分箱内的数据条数
    8. // x: [ x0, x1, x2, x3, x4, x5 ], y: [ y0, y1, y2, y3, y4, y5 ]
    9. // count: Number
    10. });
    11. /*
    12. * 顶点顺序:
    13. * 3
    14. * 4 2
    15. *
    16. * 5 1
    17. * 0
    18. */

    bin.rectangle 矩形分箱

    双字段

    alias: bin.rect

    具体用法见示例:

    1. dv.transform({
    2. type: 'bin.rectangle',
    3. fields: [ 'a', 'b' ], // 对应坐标轴上的一个点
    4. bins: [ 30, 30 ], // 两个方向上的分箱个数
    5. binsWidth: [ 10, 10 ], // 两个方向上的分箱步长(会覆盖bins配置)
    6. offset: [ 0, 0 ], // 两个方向上的分箱偏移量
    7. sizeByCount: false, // 是否根据分箱个数调整分箱大小
    8. as: [ 'x', 'y', 'count' ], // 这个点落在的六边形的顶点坐标集
    9. // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
    10. // count: Number
    11. });
    12. /*
    13. * 顶点顺序:
    14. * 3 - 2
    15. * | |
    16. * 0 - 1
    17. */

    核函数相关

    用于画核函数概率密度回归曲线,支持单字段或者双字段。

    具体用法见示例:

    • cosine
    • epanechnikov
    • gaussian (default)
    • quartic
    • triangular
    • tricube
    • triweight
    • uniform

      kernel-smooth.density 核函数概率密度分布

    用于画核函数概率密度分布热力图,双字段。

    具体用法见示例:

    1. dv.transform({
    2. type: 'kernel-smooth.density',
    3. fields: [ 'x', 'y' ], // 必填
    4. method: 'gaussian', // 采用的核函数类型。也可以指定为自定义的函数
    5. extent: [ [ min(x), max(x) ], [ min(y), max(y)] ], // 数值范围,默认为 x 以及 y 字段各自的数值范围
    6. bandwidth: 0.4, // 步长,默认采用 silverman 的算法计算
    7. as: [ 'x', 'y' ], // 结果字段,单字段时,y 为 x 值对应的概率
    8. });
    silverman 提出的 bandwidth 计算算法: paper

    支持的核函数类型同上

    hierarchy.treemap 树形图

    alias: treemap

    根据树形数据生成树形图 Treemap 布局。

    具体用法见示例:

    1. dv.transform({
    2. type: 'hierarchy.treemap',
    3. field: 'value',
    4. tile: 'treemapSquarify', // 布局类型
    5. size: [ 1, 1 ], // width, height
    6. round: false,
    7. // ratio: 1.618033988749895, // golden ratio
    8. padding: 0, // 各种 padding 配置
    9. paddingInner: 0,
    10. paddingOuter: 0,
    11. paddingTop: 0,
    12. paddingRight: 0,
    13. paddingBottom: 0,
    14. paddingLeft: 0,
    15. as: [ 'x', 'y' ] // 矩形的顶点集
    16. // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
    17. });

    支持的布局类型:

    • treemapBinary
    • treemapDice
    • treemapSlice
    • treemapSliceDice
    • treemapSquarify
    • treemapResquarify

      hierarchy.partition 相邻层次图

    alias: adjacency

    根据树形数据生成相邻层次图 Adjacency Diagram 布局,可以通过坐标变换变形为 Sunburst 图。

    具体用法见示例:

    1. dv.transform({
    2. type: 'hierarchy.partition',
    3. field: 'value',
    4. size: [ 1, 1 ], // width, height
    5. round: false,
    6. // ratio: 1.618033988749895, // golden ratio
    7. padding: 0, // 各种 padding 配置
    8. as: [ 'x', 'y' ], // 矩形的顶点集
    9. // x: [ x0, x1, x2, x3 ], y: [ y0, y1, y2, y3 ]
    10. });

    图相关

    diagram.arc 弧长链接图

    弧长链接图(Arc Diagram)可以变形为和弦图(Chord Diagram)。

    具体用法见示例:

    1. dv.transform({
    2. type: 'diagram.arc',
    3. y: 0,
    4. thickness: 0.05, // 节点高度,区间 (0, 1)
    5. weight: false, // 是否带权重,无权重为弧长链接图,带权重为和弦图
    6. marginRatio: 0.1, // 空隙比例,区间[0, 1)
    7. id: node => node.id, // 获取节点id
    8. source: edge => edge.source, // 获取边起始点id
    9. target: edge => edge.target, // 获取边结束点id
    10. sourceWeight: edge => edge.value, // 获取边起始点权重
    11. targetWeight: edge => edge.value1, // 获取边结束点权重
    12. sortBy: null, // 排序,可以按照id,权重('weight')或者边数量('frequency')排序,也可以自定排序函数
    13. });
    注意!这个 Transform 做完之后,有两部分数据(顶点和边数据),G2 在使用是不能直接通过 chart.source(dv) 来导入数据,只能分别导入顶点和边集合,例如:
    1. const nodeView = chart.view();
    2. nodeView.source(dv.nodes);
    3.  
    4. const edgeView = chart.view();
    5. edgeView.source(dv.edges);

    diagram.sankey 桑基图

    alias: sankey

    具体用法见示例:

    1. dv.transform({
    2. type: 'diagram.sankey',
    3. value: node => node.value, // 权重
    4. source: edge => edge.source, // 边起点id
    5. target: edge => edge.target, // 边终点id
    6. nodeAlign: 'sankeyJustify', // sankeyLeft / sankeyRight / sankeyCenter
    7. nodeWidth: 0.02, // 节点宽,范围:(0, 1)
    8. nodePadding: 0.02, // 节点上下间距,范围:(0, 1)
    9. });
    注意!这个 Transform 做完后同样需要注意上述 arc transform 一样的数据导入问题

    diagram.voronoi

    voronoi 图

    alias: voronoi

    具体用法见示例:

    1. dv.transform({
    2. type: 'diagram.voronoi',
    3. fields: [ 'field0', 'field1' ], // 对应坐标轴上的一个点
    4. extend: [ [ x0, y0 ], [ x1, y1 ] ], // 范围
    5. size: [ width, height ], // 范围
    6. as: [ 'x', 'y' ], // 每个点包围多边形的顶点集
    7. // x: [ x0, x1, x2, ... ], y: [ y0, y1, y2, ... ]
    8. })

    Geo 地理数据相关

    geo.projection 地理映射

    具体用法见示例:

    1. dv.transform({
    2. type: 'geo.projection',
    3. projection: 'geoAiry', // 指定映射类型
    4. as: [ 'x', 'y', 'centroid_x', 'centroid_y' ], // x,y是对应多边形的顶点集
    5. // centroid_x是中心点的x坐标
    6. // centroid_y是中心点y坐标
    7. });

    geo.centroid 由地名获取地理位置点

    具体用法见示例:

    1. dv.transform({
    2. type: 'geo.centroid',
    3. field: 'name', // 标注地名的字段
    4. geoDataView: geoDataView, // 使用的geo数据来源,可以是DataView实例,也可以是DataView实例的name
    5. as: [ '_centroid_x', '_centroid_y' ], // _centroid_x是中心点的x坐标
    6. // _centroid_y是中心点y坐标
    7. });

    geo.region 由地名获取地理位置区域

    具体用法见示例:

    1. dv.transform({
    2. type: 'geo.region',
    3. field: 'name', // 标注地名的字段
    4. geoDataView: geoDataView, // 使用的geo数据来源,可以是DataView实例,也可以是DataView实例的name
    5. as: [ '_x', '_y' ], // 多边形的顶点集
    6. // _x: [ x0, x1, x2, ... ], _y: [ y0, y1, y2, ... ]
    7. });
    alias: word-cloud

    具体用法见示例:

    1. dv.transform({
    2. type: 'tag-cloud',
    3. fields: [ 'text', 'value' ], // 参与标签云layout的字段集(前者为文本内容,后者为权重值)
    4. font: 'serif', // 标签字体
    5. size: [ 500, 500 ], // 画布size,[ width, height ]
    6. padding: 0,
    7. spiral: 'archimedean', // 标签螺旋排布规律函数 'archimedean' || 'rectangular' || {function}
    8. fontSize(d) { return d.value }, // 计算标签字体大小的回调函数,d为一行数据
    9. timeInterval: Infinity, // 最大迭代时间,默认为无限大
    10. })
    带图片形状的词云布局实例

    绘图属性

    原文: