視覺化圖表系列--點圖指北
簡單來講,使用點或者小圓形來對資料進行視覺化編碼的圖都可以稱之為點圖。到具體的應用場景,點圖被抽象出了很多圖表型別,這些圖表的使用也常常讓人迷惑。本文將具體的講解點圖的概念和使用。
本文你將學習到:
什麼是點圖?
點圖的使用場景有哪些?
點圖的優缺點有哪些?
如何建立點圖?
1。常見點圖
點圖的常見應用領域和
直方圖
有些類似,都是用來表達資料分佈,點圖在視覺上透過點的聚集形式來表現,而不是透過直接的頻率數值。點圖中的點和資料項是一一對應的關係。下面我們看幾種常見的點圖。
1.1 克利夫蘭點圖(Cleveland dot plot)
克利夫蘭點圖通常用來展示分類資料,展現形式上,數值一般分佈在
橫軸
上。我們可以透過橫向柱形圖來理解克利夫蘭點圖。
首先我們基於ChartSpace 來建立一個條形圖,輸入如下spec-1:
{
“type”
:
“horizontalBar”
,
“data”
:
[
{
“name”
:
“data1”
,
“values”
:
[
{
“x”
:
“折線圖”
,
“y”
:
82
},
{
“x”
:
“條形圖”
,
“y”
:
50
},
{
“x”
:
“餅圖”
,
“y”
:
64
},
{
“x”
:
“地圖”
,
“y”
:
30
},
{
“x”
:
“雷達圖”
,
“y”
:
40
}
]
}
],
“xField”
:
“y”
,
“yField”
:
“x”
,
“bandPadding”
:
0。3
}
spec-1
效果如下:
下面我們每一條柱子的末端新增一個圓點。
在上面的spec的最外層新增如spec-2配置:
“extensionMarks”
:
[
{
“name”
:
“dot”
,
“type”
:
“symbol”
,
“shape”
:
“circle”
,
“from”
:
{
“mark”
:
“bar”
},
//
spec中定義的mark
名字
“spec”
:
{
“normal”
:
{
“size”
:
(item
,
scale,
ctx)
=>
{
//
item是對symbol圖元的描述
return
item。height/2;
},
“fill”
:
“red”
,
“x”
:
(item
,
scale,
ctx)
=>
{
return
item。x2;
},
“y”
:
(item
,
scale,
ctx)
=>
{
return
item。y+item。height/2;
},
}
}
}
]
spec-2
結果如下:
最後我們將柱子隱藏掉。
繼續新增如下配置:
“barSpec”
:
{
“visible”
:
false
}
,
結果如下:
我們得到了一個標準的克利夫蘭點圖,這個過程是該點圖的誕生過程,但是我們在ChartSpace 裡有更加簡便的生成方法——直接使用
散點圖
型別。示例如spec-3:
{
“type”
:
“scatter”
,
“direction”
:
“horizontal”
,
“xField”
:
“x”
,
“yField”
:
“y”
,
“groupBy”
:
“x”
,
“size”
:
25
,
“data”
:
[
{
“name”
:
“data1”
,
“values”
:
[
{
“x”
:
“折線圖”
,
“y”
:
82
},
{
“x”
:
“條形圖”
,
“y”
:
50
},
{
“x”
:
“餅圖”
,
“y”
:
64
},
{
“x”
:
“地圖”
,
“y”
:
30
},
{
“x”
:
“雷達圖”
,
“y”
:
40
}
]
}
]
}
spec-3
注意上面配置的加粗部分,我們使用了圖表的
direction
****欄位來控制x,y軸資料對映,預設情況下分類資料對映到x軸,效果如下:
1.2 棒棒糖圖(Lollipop Plot)
棒棒糖圖就像它的名字一樣,由一個大的圓點和一條從
座標軸
底部出發的直線連線而成,形成一個棒棒糖的形狀。直線和圓點可以是同一組資料,也可以是不同的資料,從而可以進行多維資料的展示。
在ChartSpace 中我們有幾種方案可以實現棒棒糖圖,一個方案類似上面的推演過程,在
柱形圖
的末端加上圓點;第二種方案是先建立散點圖,在散點圖的基礎上新增豎線或者橫線。
我們採用第二種方案,如下spec-4:
//
宣告圖表
spec
const
spec
=
{
“type”
:
“scatter”
,
“xField”
:
“x”
,
“yField”
:
“y”
,
“groupBy”
:
“x”
,
“size”
:
25
,
“data”
:
[
{
“name”
:
“data1”
,
“values”
:
[
{
“x”
:
“折線圖”
,
“y”
:
82
},
{
“x”
:
“條形圖”
,
“y”
:
50
},
{
“x”
:
“餅圖”
,
“y”
:
64
},
{
“x”
:
“地圖”
,
“y”
:
30
},
{
“x”
:
“雷達圖”
,
“y”
:
40
}
]
}
],
“extensionMarks”
:
[
{
“name”
:
“markRule”
,
“type”
:
“rule”
,
“from”
:
{
“data”
:
“data1”
},
“spec”
:
{
“normal”
:
{
x:
(datum,
_scale,
ctx)
=>
{
return
ctx。chart。getPositionX(datum。x);
},
y:
(datum,
_scale,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionY(datum。y);
},
x2:
(datum,
_scale,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionX(datum。x);
},
y
2
:
(datum
,
_scale
,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionY(0);
}
}
}
}
],
}
;
spec-4
結果如下圖:
現實生活中,棒棒糖有很多不同的形狀,我們也可以透過自定義散點圖的 symbolSpec 來展現不同的形狀。
在spec-4 的基礎上,我們繼續新增如下程式碼:
symbolSpec:
{
“normal”
:
{
“shape”
:
{
“type”
:
“ordinal”
,
“field”
:
“x”
,
“range”
:
[
“circle”
,
“diamond”
,
“square”
,
“triangle”
,
“rect”
]
}
}
}
spec-4
spec-4 使用的是ChartSpace 的視覺通道語法。我們來看一下效果。
更進一步的,我們可以使用圖片來進行更有趣的自定義效果,增強故事性,比如展現不同的奧特曼的戰力。
{
“type”
:
“scatter”
,
“xField”
:
“x”
,
“yField”
:
“y”
,
“groupBy”
:
“x”
,
“size”
:
25
,
“data”
:
[
{
“name”
:
“data1”
,
“values”
:
[
{
“x”
:
“雷傑多”
,
“y”
:
900000
},
{
“x”
:
“奧特之王”
,
“y”
:
509876
},
{
“x”
:
“諾亞奧特曼”
,
“y”
:
1000000
},
{
“x”
:
“銀河奧特曼”
,
“y”
:
357890
},
{
“x”
:
“賽迦奧特曼”
,
“y”
:
897656
}
]
}
],
“extensionMarks”
:
[
{
“name”
:
“markRule”
,
“type”
:
“rule”
,
“from”
:
{
“data”
:
“data1”
},
“spec”
:
{
“normal”
:
{
x:
(datum,
_scale,
ctx)
=>
{
return
ctx。chart。getPositionX(datum。x);
},
y:
(datum,
_scale,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionY(datum。y);
},
x2:
(datum,
_scale,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionX(datum。x);
},
y
2
:
(datum
,
_scale
,
ctx)
=>
{
const
chart
=
ctx。chart;
return
ctx。chart。getPositionY(0);
}
}
}
}
,
{
“name”
:
“markImage”
,
“type”
:
“image”
,
“from”
:
{
“mark”
:
“markRule”
},
“spec”
:
{
“normal”
:
{
x:
(item,
_scale,
ctx)
=>
{
return
item。bounds。x1
-
25;
},
y:
(item,
_scale,
ctx)
=>
{
return
item。bounds。y1
},
“width”
:
50
,
“url”
:
(item
,
_scale,
ctx)
=>
{
switch
(item。datum。x)
{
case
“雷傑多”
:
return
“1。png”
;
break;
case
“奧特之王”
:
return
“2。png”
;
break;
case
“諾亞奧特曼”
:
return
“3。png”
;
break;
case
“銀河奧特曼”
:
return
“4。png”
;
break;
case
“賽迦奧特曼”
:
return
“5。png”
;
break;
}
}
}
}
}
],
symbolSpec:
{
“normal”
:
{
“fillOpacity”
:
0
}
}
}
spec-5
在上面的例子中,我們充分使用了ChartSpace的擴充套件能力,首先我們透過
symbolSpec:
{
“normal”
:
{
“fillOpacity”
:
0
}
}
隱藏了預設的點,在
extensionMarks
配置中使用了兩種自定義mark 的方式:
基於data,添加了
rule
型別的mark,名為 “markRule”,作為棒棒糖的“棍”;
基於mark,隨後基於 “markRule” 的mark,取得其
座標值
,添加了圖片型別的mark,名為 “markImage”;
效果如下圖:
1.3 啞鈴圖(Dumbbell Plot)
啞鈴圖也很好理解,就是將兩個圓點用一條線連線起來,通常用於多組資料之間的指標對比。和幫幫圖類似,我們使用堆積柱形圖來演示啞鈴圖的由來。
我們首先定義一個堆積分組柱形圖
{
“type”
:
“horizontalBar”
,
“data”
:
[
{
“name”
:
“data1”
,
“values”
:
[
{
“x”
:
“折線圖”
,
“y”
:
82
,
“type”
:
“1”
},
{
“x”
:
“條形圖”
,
“y”
:
50
,
“type”
:
“1”
},
{
“x”
:
“折線圖”
,
“y”
:
64
,
“type”
:
“2”
},
{
“x”
:
“條形圖”
,
“y”
:
30
,
“type”
:
“2”
}
]
}
],
“type”
:
“horizontalBar”
,
“xField”
:
“y”
,
“yField”
:
“x”
,
“groupBy”
:
“type”
,
“stackBy”
:
“x”
,
“bandPadding”
:
0。2
}
spec-6
效果如下:
然後利用spec-2 的方式轉換為點圖,
“extensionMarks”
:
[
{
“name”
:
“dot”
,
“type”
:
“symbol”
,
“shape”
:
“circle”
,
“from”
:
{
“mark”
:
“bar”
},
//
spec中定義的mark
名字
“spec”
:
{
“normal”
:
{
“size”
:
(item
,
scale,
ctx)
=>
{
//
item是對symbol圖元的描述
return
item。height/2;
},
“fill”
:
(item
,
scale,
ctx)
=>
{
return
item。fill;
},
“x”
:
(item
,
scale,
ctx)
=>
{
return
item。x2;
},
“y”
:
(item
,
scale
,
ctx)
=>
{
return
item。y+item。height/2;
},
}
}
}
]
,
“barSpec”
:
{
“visible”
:
false
}
,
spec-7
效果如下:
下面我們再新增一組矩形來進行連線:
“extensionMarks”
:
[
(。。。。略)
{
“name”
:
“line”
,
“type”
:
“rect”
,
“from”
:
{
“mark”
:
“bar”
,
},
//
spec中定義的mark
名字
“spec”
:
{
“normal”
:
{
“height”
:
20
,
“stroke”
:
“#0000”
,
“visible”
:
(item)=>
{
return
item。datum。type===
“2”
},
“width”
:
(item
,
scale,
ctx)
=>
{
return
item。width;
},
“fill”
:
(item
,
scale,
ctx)
=>
{
return
item。fill;
},
“x”
:
(item
,
scale,
ctx)
=>
{
return
item。x2+item。height
/
4;
},
“y”
:
(item
,
scale
,
ctx)
=>
{
return
item。y
+
item。height
/
2;
},
}
}
}
]
spec-8
效果如下:
從上面的變換過程來看,啞鈴圖和分組柱圖一樣,可以進行資料的分組和比對,同時又增加了資料變換的展示功能。
1.4 氣泡圖(Bubble Plot)
氣泡圖和普通散點圖的區別在於,資料條目可以多一個欄位來編碼到點的大小(Size)上,使得氣泡圖比普通散點圖可以對映更多維度的資料。
我們可以基於上面展示的擴充套件能力,在普通散點圖的基礎上,擴充套件點的Size 屬性,來實現氣泡圖。
“symbolSpec”
:
{
“normal”
:
{
“size”
:
{
“field”
:
“size”
,
“range”
:
[
5
,
20
],
“type”
:
“linear”
}
}
}
spec-9
效果如下:
1.5 散點地圖(Scatter Map)
散點地圖是將點的位置和地理位置相結合的一種資料視覺化方法,透過顏色區間,點的大小來編碼不同地理區域相關維度的資料,比如人口,國民生產總值,輿情資訊等。比如下圖:
1.6 範圍圖(Range Charts )
範圍圖並不屬於點圖,但是和點圖有很強的關聯關係,就像點圖和柱形圖的關係一樣。範圍圖用來展示資料範圍,是由啞鈴圖變種而來,將啞鈴圖的兩個”啞鈴“隱藏掉就是範圍圖。基於上面的實現,我們只需隱藏堆積柱形圖下面的柱子即可。如下spec
{
“type”
:
“bar”
,
“xField”
:
“x”
,
“yField”
:
“y”
,
“groupBy”
:
“type”
,
“data”
:
[
{
“name”
:
“data”
,
“values”
:
[
{
“x”
:
“2:00”
,
“y”
:
82
,
“type”
:
“銷售額”
},
(略……)
{
“x”
:
“22:00”
,
“y”
:
78
,
“type”
:
“利潤”
}
]
}
],
“bandPadding”
:
0。2
,
“paddingInGroup”
:
0。2
,
“barSpec”
:
{
“visible”
:
(item)
=>
{
return
item。type
===
“銷售額”
}
}
}
spec-10
展示效果如下:
1.7 蜂群圖
蜂群圖從展現形式上來說和普通散點圖沒有什麼區別,將每一個數據項展示成點。根本區別在於對資料的處理,蜂群圖採用了一種邏輯,以確保所繪製的點彼此靠近且不會重疊,並能有效呈現出點分佈的區域性密度資訊,直觀而不失優雅。在反映密度分佈的整體趨勢上,蜂群圖也類似箱線圖或提琴圖。相比之下,蜂群圖本身由單個樣本點組成,因此除了能夠描述整體,還能比較區域性,可以說內容更詳細
。
## 點圖的優缺點
與柱形圖相比,點圖更能節省“墨水( The data-ink ratio )”,可以留下更多的空間給資料註釋。
點圖關注的資料範圍,使用寬、高、大小、顏色、相對位置來進行資料編碼,不是很注重和座標軸之間的關係,使得軸的使用更靈活。
雖然在實現上可以由柱圖進行擴充套件,但是點圖可以表達柱圖表現不了的資料分佈,以及可以展現多維資料。
但是在數值比對的場景下,點圖是不如柱圖直觀的。
## 最佳實踐
3.1 顏色
由於常規點圖形狀大小沒有差別,顏色的使用就至關重要。
連續資料
在展示連續資料的時候,可以使用連續的顏色為點進行著色,同時配合連續顏色圖例進行資料篩選。
分類資料
分類資料要求在顏色區分度上比較明顯,當然我們可以輔助形狀來加強使用者對分類的識別。
時序資料
時序時間的顏色編碼,通常按照時間由遠到近逐漸加深顏色,以檢視特定資料的時間分佈。比如下圖,不同顏色表示的是不同的年份。
3.2 組合應用
將點圖與其他圖表進行組合,可以很有效的展示覆雜的資料。下圖使用點圖來展現範圍,用柱圖來表達值的大小。
下圖使用點圖和線圖進行組合,展現資料範圍和平均值的變化趨勢。
下圖組合散點圖和和啞鈴圖,表示範圍和某一範圍內的資料波動情況。
資料平臺前端團隊,在公司內負責大資料相關產品的研發。我們在前端技術上保持著非常強的熱情,除了資料產品相關的研發外,在資料視覺化、海量資料處理最佳化、web excel、WebIDE、私有化部署、工程工具都方面都有很多的探索和積累,有興趣可以與我們聯絡。
本文中的 ChartSpace 為我們內部自研圖表框架。