可視化架構設計-資料類型,可視化架構資料類型
資料類型
簡介
資料視覺效果的本質就是將資料對應到圖形,不同資料類型的資料適合的圖形屬性也不一樣,本章講解資料分類和G2是如何設計資料分類。圖形屬性在下一章節視覺通道中講解。
資料類型
資料的類型可以按照兩種分類方式:
* 資料自然的分類
* 資料是否連續
資料自然的分類
按照資料的自然分類,可以將數實值型別分為:
* 名詞:常見的名詞,不關心順序,比如國家的名稱
* 有序:有序的分類,例如警報資訊,從低到高分為黃色警告、橙色警告和紅色警告
* 間隔:有間隔的數字,不考慮0的意義。例如溫度,0度不代表沒有溫度
* 比例:表示欄位之間存在比例關係,0必須有意義。
資料是否連續
按照資料是否連續劃分的方式:
+ 分類(定性)資料,又分為有序的分類和無序的分類
+ 連續(定量)資料,連續不間斷的數值,時間也是一種連續的資料類型
首先我們來看一下下面的資料:
[{"month":"一月","temperature":7,"city":"tokyo"},{"month":"二月","temperature":6.9,"city":"newYork"},{"month":"三月","temperature":9.5,"city":"tokyo"},{"month":"四月","temperature":14.5,"city":"tokyo"},{"month":"五月","temperature":18.2,"city":"berlin"}]
其中:month 代表月份,temperature 代表溫度,city 代表城市
- 上面資料中
month和city都是離散的分類,但是又有所差異。month是有序的分類類型,而city是無序的分類類型。
- temperature 是連續的數字
如何設計資料類型-度量
我們在G2中將資料類型按照是否連續來劃分,每種分類設計成不同的度量(Scale),度量用於完成以下功能:
所以每種度量必須包含以下資訊:
- 定義域(domain),分類度量指的是各種分類,連續度量的最小值、最大值
- 範圍(range),將分類、連續資料對應到範圍,預設 0-1
- 座標點(ticks),用於顯示在圖例或者座標軸上,對於分類度量,座標點就是分類類型;連續的資料類型,需要計算出對人比較友好的座標點、友好的座標間距,例如:
- 1,2,3,4,5
- 0, 5,10,15,20
- 0.001, 0.005,0.010
而不是:
- 1.1,2.1,3.1,4.1
- 12,22,32,42,52
支援的度量
G2中提供了下面幾種度量
- identity,常量類型的數值,也就是說資料的某個欄位是不變的常量;
- linear,連續的數字 [1,2,3,4,5];
- cat,分類, [‘男’,’女’];
- time,連續的時間類型;
- log,連續非線性 Log 資料 將 [1,10,100,1000] 轉換成[0,1,2,3];
- pow,連續非線性 pow 資料 將 [2,4,8,16,32] 轉換成 [1,2,3,4,5];
- timeCat,非連續的時間,比如股票的時間不包括周末或者未開盤的日期。
屬性和介面設計
度量共有的屬性:
| 屬性名稱 |
說明 |
| type |
度量類型 |
| range |
度量轉換的範圍,預設是[0,1] |
| alias |
別名,大多數資料集合的欄位名都是英文,有時候需要定義中文名稱,便於在圖例、提示資訊上顯示 |
| ticks |
支援的座標點,可以在圖例、座標軸上顯示,座標點的計算後面詳細介紹 |
| tickCount |
座標點的個數,不同類型的度量預設值不同 |
| formatter |
輸出欄位時的格式化函數,會影響資料在座標軸、圖例、提示資訊(tooltip)上的顯示 |
linear
連續的資料類型的基類,包含以下特殊的屬性
| 屬性名稱 |
說明 |
| min |
定義域的最小值 |
| max |
定義域的最大值 |
| tickCount |
連續類型的度量,預設產生座標點的個數是5 |
| tickInterval |
用於指定座標軸各個標度點的間距,是未經處理資料之間的間距差值,tickCount 和 tickInterval 不可以同時聲明 |
| nice |
是否根據人對數字識別的友好度,來調整min和max。例如 min:3,max: 97,如果nice: true,那麼會自動調整為:min: 0,max: 100 |
cat
分類類型度量的特殊屬性
G2建立圖表的時候,values欄位一般會自動從資料中取得,但是以下2中情形下需要使用者手動指定
需要指定分類的順序時,例如:type 欄位有’最大’,’最小’和’適中’3種類型,我們想指定這些分類在座標軸或者圖例上的順序時:
[{a: 'a1', b:'b1', type: '最小'},{a: 'a2', b:'b2', type: '最大'},{a: 'a3', b:'b3', type: '適中'}]var defs = {'type': {type: 'cat',values: ['最小','適中','最大']}};
如果不聲明度量的values欄位,那麼預設的順序是:‘最小’,‘最大’,‘適中’
如果資料中的分類類型使用枚舉的方式表示,那也也需要指定values
[{a: 'a1', b:'b1', type: 0},{a: 'a2', b:'b2', type: 2},{a: 'a3', b:'b3', type: 1}]var defs = {'type': {type: 'cat',values: ['最小','適中','最大']}};
必須指定’cat’類型,values的值按照索引跟枚舉類型一一對應
time
time類型是一種特殊的連續型數值,所以我們將time類型的度量定義為linear的子類,除了支援所有通用的屬性和linear度量的屬性外,還有自己特殊的屬性:
| 屬性名稱 |
說明 |
| mask |
資料的格式化格式 預設:’yyyy-mm-dd’ |
目前支援 2 種類型的時間(time)類型:
- 時間戳記的數字形式, 1436237115500 // new Date().getTime()
- 時間字串: ‘2015-03-01’, ‘2015-03-01 12:01:40’, ‘2015/01/05’,’2015-03-01T16:00:00.000Z’
格式化日期時mask的預留位置:
- y: year
- m: month
- d: date
- H: hour
- M: minute
- s: second
log
log類型的資料可以將非常大範圍的資料對應到一個均勻的範圍內,這種度量是linear的子類,支援所有通用的屬性和linear度量的屬性,特有的屬性:
| 屬性名稱 |
說明 |
| base |
Log 的基數,預設是2 |
以下情形下建議使用log度量
- 散佈圖時資料的分布非常廣,同時資料分散在幾個區間內。例如 分布在 0-100, 10000 - 100000, 1千萬 - 1億內,這時候適合使用log 度量
- 使用熱力圖時,資料分布不均勻時也會出現只有非常高的資料點附近才有顏色,此時需要使用log度量,對資料進行log處理。
pow
pow類型的資料也是linear類型的一個子類,除了支援所有通用的屬性和linear度量的屬性外也有自己的屬性:
timeCat
timeCat類型的資料,是一種日期資料,但是不是連續的日期。例如代表存在股票交易的日期,此時如果使用time類型,那麼節假日沒有資料,折線圖、k線圖會斷裂,所以此時使用timeCat的度量表示分類的日期,預設會對資料做排序。
| 屬性名稱 |
說明 |
| tickCount |
此時需要設定座標點的個數 |
| mask |
資料的格式化格式 |
度量座標點的計算
度量的資訊需要在圖例、座標軸上顯示時,不可能全部顯示所有的資料,那麼就需要選取一些代表性的資料顯示在圖例、座標軸上,我們稱這些資料為ticks(座標點),不同的類型的度量計算ticks(座標點)的演算法各不一樣,我們這裡提供3類度量ticks(座標點)的計算:
- 分類度量,包括 cat,timeCat
- 連續類型度量,包括linear,log,pow
- 時間類型度量,包括time
分類度量的計算
分類度量一般情況下不需要計算ticks,直接將所有的分類在圖例、座標軸上顯示出來即可
但是當分類類型的數值過多,同時分類間有循序關聯性時可以省略掉一些分類例如:
計算時需要使用到的屬性:
- values: 當前度量的分類值,如果未指定,則直接從資料來源中提取
- tickCount: 保留幾個座標點
分類的ticks計算非常簡單個
- 均勻的從values中取tickCount個座標點
- 為了保證values第一個和最後一個value都在ticks中,取值的間隔是 (values.length - 1) / (tickCount - 1),則保證values第一個和最後一個value都在ticks中
整除的情境:
var values= ["第一周","第二周","第三周","第四周","第五周","第六周","第七周","第八周","第九周"];var tickCount = 5;// 由於 values.length = 9;// 平均間隔 step = (9 - 1) / (5 - 1) = 2;var ticks = ["第一周","第三周","第五周","第七周","第九周"]
不能整除:
var values= ["第一周","第二周","第三周","第四周","第五周"];var tickCount = 4;// 由於 values.length = 5;// 平均間隔 step = (5 - 1) / (4 - 1) = 4/3; 取整 step = 1;// 捨棄了第四周var ticks = ["第一周","第二周","第三周","第五周"]
連續資料度量的計算
連續資料類型計算座標點需要考慮以下問題:
- 座標點必須是對人友好的資料(nice numbers),不能簡單的均分的方式計算座標點。
例如 min: 3,max: 97,tickCount: 6,如果平均劃分則會產生 ticks: [3, 21.8,40.6,59.4,78.2,97],我們理想的方式是ticks: [0, 20, 40, 60, 80, 100]
- 計算的數值範圍不確定,有可能是 0, 100, 1000 也有可能是 0.01,0.02,0.03
連續資料座標點的計算方式如下:
- 指定一個逼近數組 [1,2,5,10],用於計算對人友好的tickInterval
- 根據傳入的min,max,tickCount 計算 tickInterval,將tickInterval的值轉換到 0-10之間,保留轉換的係數,例如min: 0, max: 9003,tickCount = 4,n那麼計算的tickInterval = 3001 變成 3.001,係數是1000,然後在逼近數組中找到一個逼近值,以 3.001為樣本
- 可以選擇向上逼近(最終產生的座標點個數小於tickCount),得出逼近值 5
- 或者選擇向下逼近(最終產生的座標點的個數大於tickCount),得出逼近值 2
- 或者四捨五入(有可能會多,有可能會少),得出逼近值5
- 將得到的逼近值乘以前面求得的係數1000,
- 如果逼近值是5,tickInterval = 1000 * 5 = 5000, 將min,和max取tickInterval的倍數,最終計算出來的ticks : [0, 5000, 10000]
- 如果逼近值是2,tickInterval = 1000 * 2 = 2000, 將min,和max取tickInterval的倍數,最終計算出來的ticks :[0, 2000, 4000, 6000, 8000, 1000]
虛擬碼如下:
var snapArray = [0, 2, 5,10];var min = 0;var max = 9003;var tickCount = 4;var tickInterval = (max - min) / (tickCount - 1); // 3001;var factor = getFactor(tickInterval)// 1000,如果value > 10 則不斷除以10 直到除數 1<value<10,如果value < 1,則不斷乘以10, 直到 1< value < 10var snapValue = snap(snapArray, tickInterval / factor, 'ceil'); // 向上逼近,逼近值5var tickInterval = snapValue * factor;var min = snapMultiple(tickInterval, min, 'floor')// 向下取tickInterval的整數倍,0var max = snapMultiple(tickInterval,max, 'ceil') //向上取tickInterval的整數倍,15000var ticks = [];for(var i = min; i <= max; i+= tickInterval){ ticks.push(i);}return ticks;
注意事項
* snapArray 可以進行調整,數組內部值越多,間距越小,計算出來的tickCount跟預期的差距越小
* min,必須向下取tickInterval的倍數,max ,必須向上取tickInterval的倍數
時間類型的度量計算座標點
時間類型的資料是連續資料,但是不適合連續資料度量的計算方式原因在於:
- 時間戳記的數值比較大,包含毫秒資訊,取對人友好的數值格式化出來的時間不一定對人友好,如 1466677570000,是 ’2016 18:26:10‘
- 對於日期的間隔大於月份,大於年的資料集,沒法取得固定的tickInterval,因為月份和年的時間間隔並不相等
所以時間類型的度量需要自己的演算法,演算法如下:
- 根據min,max 和 tickCount計算tickInterval;
- 計算tickInterval 佔一年的比例,yfactor = interval / yms(一年的毫秒數)
- 如果yfactor > 0.51,也就是時間間隔大於半年,取min和max的年份,按照年計算ticks
例如: min: 2001-05-02, max: 2015-10-12, tickCount = 6,此時ticks = [2001-01-01,2004-01-01 2007-01-01,2010-01-01, 2013-01-01, 2016-01-01]
- 如果0.0834 < yfactor < 0.51,時間間隔大於一個月,那麼就按月的倍數來計算ticks
例如: min: 2001-05-02,max: 2002-04-03, tickCount = 5, 此時ticks = [2001-05-01, 2001-07-01, 2001-09-01, 2001-11-01, 2002-02-01, 2002-04-01, 2001-06-01]
- 如果時間間隔大於1天,按照天的倍數計算;如果時間間隔大於一個小時,按照小時的倍數計算。。。。然後按照分、秒、毫秒計算ticks
注意事項:
- tickCount的值也無法確定最終產生的ticks的個數
- 必須保證計算出來的ticks的第一個值小於min,最後一個值大於max
更多
本章講解了資料分類和G2如何設計資料分類,並且提供了計算座標點(ticks)的方法,圖例和座標軸顯示的文本全部由本章講解的度量所決定,下一章節講解視覺通道,並講解視覺通道跟資料分類的關係。
G2網站:https://g2.alipay.com/