關於 ECharts4 新增的資料集(dataset)

ECharts發表於2018-01-18

ECharts 4 開始有了 `資料集`(`dataset`)元件來單獨宣告資料,大概長這個樣子:

option = {
    dataset: {
        // 提供一份資料。
        source: [
            ['product', '2015', '2016', '2017'],
            ['Matcha Latte', 43.3, 85.8, 93.7],
            ['Milk Tea', 83.1, 73.4, 55.1],
            ['Cheese Cocoa', 86.4, 65.2, 82.5],
            ['Walnut Brownie', 72.4, 53.9, 39.1]
        ] 
    },
    legend: {},
    tooltip: {},
    // 宣告一個 X 軸,類目軸(category)。預設情況下,類目軸對應到 dataset 第一列。
    xAxis: {type: 'category'},
    // 宣告一個 Y 軸,數值軸。
    yAxis: {},
    // 宣告多個 bar 系列,預設情況下,每個系列會自動對應到 dataset 的每一列。
    series: [
        {type: 'bar'},
        {type: 'bar'},
        {type: 'bar'}
    ]
} 
複製程式碼


這個最簡單的例子,得到的效果是這樣的:

關於 ECharts4 新增的資料集(dataset)


資料集帶來的好處是:

  • 有了 `dataset` 後,能夠貼近這樣的資料視覺化常見思維方式:基於資料(`dataset` 元件來提供資料),指定資料到視覺的對映(由 `encode` 屬性來指定對映),形成圖表。
  • 資料和其他配置可以被分離開來,使用者相對便於進行單獨管理,也省去了一些資料處理的步驟。
  • 資料可以被多個系列或者元件複用,對於大資料,不必為每個系列建立一份。
  • 支援更多的資料的常用格式,例如二維陣列、物件陣列等,一定程度上避免使用者為了資料格式而進行轉換。


資料到圖形的對映


本篇裡,我們製作資料視覺化圖表的邏輯是這樣的:基於資料,在配置項中指定如何對映到圖形。

概略而言,可以進行這些對映:

  • 指定 dataset 的列(column)還是行(row)對映為圖形系列(series)。這件事可以使用 `series.seriesLayoutBy` 屬性來配置。
  • 指定 dataset 的哪些列(column)或行(row)對應到座標軸(如 X、Y 軸)、提示框(tooltip)、標籤(label)、圖形元素大小顏色等(visualMap)。這件事可以使用 `series.encode` 屬性來配置。如果有需要對映顏色大小等視覺維度,可以使用 visualMap 元件。


按行還是按列做對映


有了資料表之後,使用者可以靈活得配置:資料如何對應到軸和圖形系列。上面的例子中,沒有給出這種對映配置,那麼ECharts 就按最常見的理解進行預設對映:

  • X 座標軸宣告為類目軸,預設情況下會自動對應到 dataset.source 中的第一列;
  • 三個柱圖系列,一一對應到 dataset.source 中後面每一列。


使用者可以使用 `seriesLayoutBy` 配置項,改變圖表對於行列的理解。`seriesLayoutBy` 可取值:

  • 'column': 預設值。系列被安放到 `dataset` 的列上面。
  • 'row': 系列被安放到 `dataset` 的行上面。


option = {
    legend: {},
    tooltip: {},
    dataset: {
        source: [
            ['product', '2012', '2013', '2014', '2015'],
            ['Matcha Latte', 41.1, 30.4, 65.1, 53.3],
            ['Milk Tea', 86.5, 92.1, 85.7, 83.1],
            ['Cheese Cocoa', 24.1, 67.2, 79.5, 86.4]
        ]
    },
    xAxis: [
        {type: 'category', gridIndex: 0},
        {type: 'category', gridIndex: 1}
    ],
    yAxis: [
        {gridIndex: 0},
        {gridIndex: 1}
    ],
    grid: [
        {bottom: '55%'},
        {top: '55%'}
    ],
    series: [
        // 這幾個系列會在第一個直角座標系中,每個系列對應到 dataset 的每一行。
        {type: 'bar', seriesLayoutBy: 'row'},
        {type: 'bar', seriesLayoutBy: 'row'},
        {type: 'bar', seriesLayoutBy: 'row'},
        // 這幾個系列會在第二個直角座標系中,每個系列對應到 dataset 的每一列。
        {type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
        {type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
        {type: 'bar', xAxisIndex: 1, yAxisIndex: 1},
        {type: 'bar', xAxisIndex: 1, yAxisIndex: 1}
    ]
}
複製程式碼

效果是這樣的:

關於 ECharts4 新增的資料集(dataset)

更重要的是,我們可以使用 `encode` 配置項來更細節得指定資料如何對映到圖形。總體是這樣的感覺:


維度(dimension)


介紹 `encode` 之前,首先要介紹“維度(dimension)”的概念。


常用圖表所描述的資料大部分是“二維表”結構,上述的例子中,我們都使用二維陣列來容納二維表。現在,當我們把系列(series)對應到“列”的時候,那麼每一列就稱為一個“維度(dimension)”,而每一行稱為資料項(item)。反之,如果我們把系列(series)對應到錶行,那麼每一行就是“維度(dimension)”,每一列就是資料項(item)。


維度可以有單獨的名字,便於在圖表中顯示。維度名(dimension name)可以在定義在 dataset 的第一行(或者第一列)。例如上面的例子中,'score'、'amount'、'product' 就是維度名。從第二行開始,才是正式的資料。`dataset.source` 中第一行(列)到底包含不包含維度名,ECharts 預設會自動探測。當然也可以設定 `dataset.sourceHeader: true` 顯示宣告第一行(列)就是維度,或者 `dataset.sourceHeader: false` 表明第一行(列)開始就直接是資料。


維度的定義,也可以使用單獨的 `dataset.dimensions` 或者 `series.dimensions` 來定義,這樣可以同時指定維度名,和維度的型別(dimension type):

var option1 = {
    dataset: {
        dimensions: [
            {name: 'score'},
            // 可以簡寫為 string,表示維度名。
            'amount',
            // 可以在 type 中指定維度型別。
            {name: 'product', type: 'ordinal'}
        ],
        source: [...]
    },
    ...
};

var option2 = {
    dataset: {
        source: [...]
    },
    series: {
        type: 'line',
        // 在系列中設定的 dimensions 會更優先採納。
        dimensions: [
            null, // 可以設定為 null 表示不想設定維度名
            'amount',
            {name: 'product', type: 'ordinal'}
        ]
    },
    ...
};
複製程式碼


大多數情況下,我們並不需要去設定維度型別,因為會自動判斷。但是如果因為資料為空之類原因導致判斷不足夠準確時,可以手動設定維度型別。


維度型別(dimension type)可以取這些值:

  • 'number': 預設,表示普通資料。
  • 'ordinal': 對於類目、文字這些 string 型別的資料,如果需要能在數軸上使用,須是 'ordinal' 型別。ECharts 預設會自動判斷這個型別。但是自動判斷也是不可能很完備的,所以使用者也可以手動強制指定。
  • 'time': 表示時間資料。設定成 'time' 則能支援自動解析資料成時間戳(timestamp),比如該維度的資料是 '2017-05-10',會自動被解析。時間型別的支援參見 [data](option.html#series.data)。
  • 'float': 如果設定成 `float`,在儲存時候會使用 `TypedArray`,對效能優化有好處。
  • 'int': 如果設定成 `float`,在儲存時候會使用 `TypedArray`,對效能優化有好處。


資料到圖形的對映(encode)


瞭解了維度的概念後,我們就可以使用 `encode` 來做對映。`encode` 宣告的基本結構如下,其中冒號左邊是座標系、標籤等特定名稱,如 `'x'`, `'y'`, `'tooltip'` 等,冒號右邊是資料中的維度名(string 格式)或者維度的序號(number 格式,從 0 開始計數),可以指定一個或多個維度(使用陣列)。通常情況下,下面各種資訊不需要所有的都寫,按需寫即可。


var option = {
    dataset: {
        source: [
            ['score', 'amount', 'product'],
            [89.3, 58212, 'Matcha Latte'],
            [57.1, 78254, 'Milk Tea'],
            [74.4, 41032, 'Cheese Cocoa'],
            [50.1, 12755, 'Cheese Brownie'],
            [89.7, 20145, 'Matcha Cocoa'],
            [68.1, 79146, 'Tea'],
            [19.6, 91852, 'Orange Juice'],
            [10.6, 101852, 'Lemon Juice'],
            [32.7, 20112, 'Walnut Brownie']
        ]
    },
    xAxis: {},
    yAxis: {type: 'category'},
    series: [
        {
            type: 'bar',
            encode: {
                // 將 "amount" 列對映到 X 軸。
                x: 'amount',
                // 將 "product" 列對映到 Y 軸。
                y: 'product'
            }
        }
    ]
};
複製程式碼

效果如下:

關於 ECharts4 新增的資料集(dataset)


下面給出個更豐富的 `encode` 的 示例


視覺通道(顏色、尺寸等)的對映


我們可以使用 `visualMap` 元件進行視覺通道的對映。這是一個示例:

var option = {
    dataset: {
        source: [
            ['score', 'amount', 'product'],
            [89.3, 58212, 'Matcha Latte'],
            [57.1, 78254, 'Milk Tea'],
            [74.4, 41032, 'Cheese Cocoa'],
            [50.1, 12755, 'Cheese Brownie'],
            [89.7, 20145, 'Matcha Cocoa'],
            [68.1, 79146, 'Tea'],
            [19.6, 91852, 'Orange Juice'],
            [10.6, 101852, 'Lemon Juice'],
            [32.7, 20112, 'Walnut Brownie']
        ]
    },
    grid: {containLabel: true},
    xAxis: {name: 'amount'},
    yAxis: {type: 'category'},
    visualMap: {
        orient: 'horizontal',
        left: 'center',
        min: 10,
        max: 100,
        text: ['High Score', 'Low Score'],
        // Map the score column to color
        dimension: 0,
        inRange: {
            color: ['#D7DA8B', '#E15457']
        }
    },
    series: [
        {
            type: 'bar',
            encode: {
                // Map the "amount" column to X axis.
                x: 'amount',
                // Map the "product" column to Y axis
                y: 'product'
            }
        }
    ]
};
複製程式碼
關於 ECharts4 新增的資料集(dataset)



幾個常見的對映設定方式


問:如何把第三列設定為 X 軸,第五列設定為 Y 軸?

答:

series: {
    encode: {x: 3, y: 5},
    ...
}
複製程式碼


問:如何把第三行設定為 X 軸,第五行設定為 Y 軸?

答:

series: {
    encode: {x: 3, y: 5},
    seriesLayoutBy: 'row',
    ...
}
複製程式碼


問:如何把第二列設定為標籤?

答:

關於標籤的顯示(`label.formatter`),現在支援使用這樣的語法:

'aaa{@product}bbb{@score}ccc{@[4]}ddd' 來引用某個具體的維度值。其中 '{@score}' 表示因為 “名為 score” 的維度裡的值,'{@[4]}' 表示引用序號為 4 的維度裡的值。

series: [{
    label: {
        show: true,
        // 標籤中引用第二列。
        formatter: 'The value at column 2 is: {@[2]}.'
    },
    ...
}, {
    label: {
        show: true,
        // 標籤中引用維度名為 product 的列。
        formatter: 'The product name is: {@product}.'
    },
    ...
}]
複製程式碼


問:如何讓第 2 列和第 3 列顯示在提示框(tooltip)中?

答:

series: {
    encode: {
        tooltip: [2, 3]
        ...
    },
    ...
}
複製程式碼


問:資料裡沒有維度名,那麼怎麼給出維度名?

答:

dataset: {
    dimensions: ['score', 'amount'],
    source: [
        [89.3, 3371],
        [92.1, 8123],
        [94.4, 1954],
        [85.4, 829]
    ]
}
複製程式碼


問:如何把第四列對映為氣泡圖的點的大小?

答:

var option = {
    dataset: {
        source: [
            [12, 323, 11.2],
            [23, 167, 8.3],
            [81, 284, 12],
            [91, 413, 4.1],
            [13, 287, 13.5]
        ]
    },
    visualMap: {
        show: false,
        dimension: 2, // 指向第三列(列序號從 0 開始記,所以設定為 2)。
        min: 2, // 需要給出數值範圍,最小數值。
        max: 15, // 需要給出數值範圍,最大數值。
        inRange: {
            // 氣泡尺寸:5 畫素到 60 畫素。
            symbolSize: [5, 60]
        }
    },
    xAxis: {},
    yAxis: {},
    series: {
        type: 'scatter'
    }
};
複製程式碼


問:encode 裡指定了對映,但是不管用?

答:可以查查有沒有拼錯,比如,維度名是:'Life Expectancy',encode 中拼成了 'Life Expectency'。



資料的各種格式


多數常見圖表中,資料適於用二維表的形式描述。廣為使用的資料表格軟體(如 MS Excel、Numbers)或者關係資料資料庫都是二維表。他們的資料可以匯出成 JSON 格式,輸入到 `dataset.source` 中,在不少情況下可以免去一些資料處理的步驟。


假如資料匯出成 csv 檔案,那麼可以使用一些 csv 工具如 [dsv](github.com/d3/d3-dsv) 或者 [PapaParse](github.com/mholt/PapaP…) 將 csv 轉成 JSON。


在 JavaScript 常用的資料傳輸格式中,二維陣列可以比較直觀的儲存二維表。前面的示例都是使用二維陣列表示。


除了二維陣列以外,dataset 也支援例如下面 key-value 方式的資料格式,這類格式也非常常見。但是這類格式中,目前並不支援 `seriesLayoutBy` 引數。


dataset: [{
    // 按行的 key-value 形式,這是個比較常見的格式。
    source: [
        {product: 'Matcha Latte', count: 823, score: 95.8},
        {product: 'Milk Tea', count: 235, score: 81.4},
        {product: 'Cheese Cocoa', count: 1042, score: 91.2},
        {product: 'Walnut Brownie', count: 988, score: 76.9}
    ]
}, {
    // 按列的 key-value 形式。
    source: {
        'product': ['Matcha Latte', 'Milk Tea', 'Cheese Cocoa', 'Walnut Brownie'],
        'count': [823, 235, 1042, 988],
        'score': [95.8, 81.4, 91.2, 76.9]
    }
}]
複製程式碼



此外,ECharts 4 之前一直以來的資料宣告方式仍然被正常支援,如果系列已經宣告瞭 `series.data`, 那麼就會使用 `series.data` 而非 `dataset`。


最後,給出一個 示例,多個圖表共享一個 `dataset`,並帶有聯動互動。


更詳細的資訊,可以參見這個 教程



相關文章