🏠 重點提要:
這一份程式筆記有兩個學習目標:
■ggplot2
套件的介紹
■ 體驗資料視覺化的威力
ggplot
是資料框視覺化的主流工具
■ 每一筆資料對應到一個繪圖元件(geom_...
),如
◇ geom_point
: 點狀圖
◇ geom_bar
, geom_col
: 柱狀圖
◇ geom_line
: 折線圖
■ 每一個欄位對應到一個繪圖元件的屬性,
◇ 如點的座標、顏色、大小、形狀等等
🌻 ggplots
中的基本程式碼元素為 …
ggplot
將資料框繪製到圖中aes
指定變數的x軸與y軸和幾何屬性的繪圖類型+
) 可以在繪圖中添加多個幾何圖形geom
)中指定載入library裡面的套件
::p_load(dplyr,tidyr,ggplot2,plotly,gridExtra)
pacmantheme_set(theme_get() + theme(# set common plotting formats
text=element_text(size=8), legend.key.size=unit(10,"points")
))
在R中繪圖很容易,讓我們使用R的內建數據iris
作為快速入門的例子。
head(iris)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa
table(iris$Species)
setosa versicolor virginica
50 50 50
在iris
資料框中,有3個不同種類,共150朵鳶尾花。
ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length, color=Species)) +
geom_point(size=2, shape=18) + theme_bw()
使用geom_point()
,iris
中的每一朵花都被繪製為一個點,它們的Sepal.Width
、Sepal.Length
和Species
分別對應到每個點的x、y坐標和顏色。點的靜態屬性(The static attribute of the points),例如size
和shape
,則直接在geom_()
中指定。
🌻 探索性分析的主要目的是:
我們再次使用漫畫人物資料集來做例子
= read.csv("data/comics1.csv",stringsAsFactors=F)
D glimpse(D)
Rows: 7,250
Columns: 9
$ publisher <chr> "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc", "dc"~
$ name <chr> "Batman (Bruce Wayne)", "Superman (Clark Kent)", "Green La~
$ align <chr> "Good", "Good", "Good", "Good", "Good", "Good", "Good", "G~
$ eye <chr> "Blue", "Blue", "Brown", "Brown", "Blue", "Blue", "Blue", ~
$ hair <chr> "Black", "Black", "Brown", "White", "Black", "Black", "Blo~
$ sex <chr> "Male", "Male", "Male", "Male", "Male", "Female", "Male", ~
$ alive <chr> "Living", "Living", "Living", "Living", "Living", "Living"~
$ appearances <int> 3093, 2496, 1565, 1316, 1237, 1231, 1121, 1095, 1075, 1028~
$ year <int> 1939, 1986, 1959, 1987, 1940, 1941, 1941, 1989, 1969, 1956~
先畫一個簡單的點狀圖
ggplot(D, aes(year,appearances)) + geom_point()
圖看起來很漂亮,但能看到什麼資訊呢?你能說出誰是出場次數最多的角色嗎?讓我們來做一些改善。
🚴 練習2A
逐步加入以下程式並觀察它們的效果…
■ 把 color=sex, shape=align
等參數,放入 aes()
裡面
■ 把 + scale_x_log10()
放在後面
■ 把 + facet_wrap(~publisher)
放在後面
圖的資訊含量變大了,但是它是不是變得非常凌亂呢?
🌻 資料視覺化的兩個目標:「資訊含量」和「簡單清楚」常常是互相衝突的
🌻 想要同時滿足這兩項目標,關鍵在於「互動性」
# take 100 most appearing characters from each publisher
= D %>% group_by(publisher) %>% # from each publisher
gg top_n(n=100, wt=appearances) %>% # pick out 100 most appearing roles
ggplot(aes(x=year,y=appearances,color=sex,shape=align, label=name)) +
scale_y_log10() +
facet_wrap(~publisher) +
geom_point(alpha=0.8) + # set transparency & size
theme_bw() + # choose a theme for clarity
theme(text=element_text(size=9)) + # use smaller font
labs(title="The Most Appearings",
x="", y="", color="", shape="") # set plot and the axis titles
我們先將圖形物件保存在叫做gg
的物件裡,接著我們利用plotly::ggplotly()
讓圖形變成可以互動
ggplotly(gg)
🚴 讓我們來體驗一下圖形的互動式吧 …
在學習繪圖的更細節的語法之前,你應該已經體驗過視覺化的威力了
🌻 互動性是現代資料視覺化的重要功能
year
與 appearances
之間的關係sex
, align
和 publisher
之間的關係是如何變化的🌻 直接從圖表中,您可以回答一些複雜的問題,像是…
🌻 回答上述某些問題,過去需要接受認真的統計學訓練。現在,有了互動式圖表,即使你根本沒有學過統計學,也可以直接觀察到答案。
🌻 建立了
讓我們在另一個例子中示範互動式圖表的分析能力
👨 🏫 如果我們想調查
角色外表(特別是頭髮
和眼睛
顏色)和陣營(align
)、性別(sex
)和傷亡(alive
)這些變數之間的相關性
並且,這些變數之間的關係如何隨時間變化?
以往我們需要建一些複雜的模型才能回答這些研究問題,現在我們可以使用互動圖表中直接回答這些問題。 首先我們需要準備資料,讓我們把時間軸設定在 1980 年至 2010 年,並將這段時間以5年為一個區間
=seq(1980,2010,5)
breaks= filter(D, year>=1980, year<=2010) %>% # set the time period
D2 mutate(
period = cut(year,breaks,breaks[-1],T) %>% # cut them into 5yr period
%>% # by default cut() returns a factor, but
as.character # we'd liker to have an integer here
as.integer )
然後我們計算每種頭髮-眼睛顏色組合的數量,並計算它們的占比和累計占比。
= count(D2, hair, eye, sort=T) %>% # count and sort
outlooks mutate(share=100*n/sum(n), cum=cumsum(share)) # shares and accumulation
head(outlooks, 20)
hair eye n share cum
1 Black Brown 770 15.625 15.62
2 Brown Brown 563 11.425 27.05
3 Blond Blue 548 11.120 38.17
4 Black Blue 351 7.123 45.29
5 Brown Blue 238 4.830 50.12
6 Black Black 226 4.586 54.71
7 others Blue 130 2.638 57.35
8 Red Green 122 2.476 59.82
9 Red Blue 119 2.415 62.24
10 White Blue 112 2.273 64.51
11 Black Green 77 1.562 66.07
12 No Green 75 1.522 67.59
13 Bald Brown 72 1.461 69.05
14 Blond Green 70 1.420 70.47
15 Brown Green 68 1.380 71.85
16 Blond Brown 65 1.319 73.17
17 Black Red 63 1.278 74.45
18 Black others 61 1.238 75.69
19 others Green 59 1.197 76.89
20 No Red 57 1.157 78.04
前 10 名的組合大概覆蓋了三分之二的人口。
資料裝配線: 在下面的程式區塊,我們示範如何運用管線符號(%>%)來建立一條資料裝配線。乍看之下,管線符號(%>%)可能會令人緊張,不過它不是一次就建立完成的,讓我們來介紹如何從頭開始逐步建立流水線吧!
inner_join(D2, outlooks[1:10,]) %>% # filter for the top 10 outlooks
group_by(hair, eye) %>% summarise( # group by hair and eye
n = n(), # count the no. characters
female=mean(sex=="Female"), # the share of female
bad=mean(align=="Bad"), # the share of bad guys
dead=mean(alive=="Deceased"), # the casualty ratio
.groups='drop') %>% # drop the remaining group
ggplot(aes(bad, dead)) + # map x and y coordinates
geom_point(aes(col=female, size=n), alpha=0.8) + # map size and color
scale_color_gradientn(colors=c("seagreen","gold","red")) + # set color scale
scale_size_continuous(range=c(3,12)) + # set size scale
geom_text(aes(label=paste(hair,eye,sep="\n")), size=3) # put on a text label
Joining, by = c("eye", "hair")
上面的圖表是有資訊含量的。 但是還不夠好…
動態和互動式圖表可以解決這些問題。 在下面的程式區塊中,我們做了一些修改…
hair
和eye
,我們還按period
分組,在每個period
都建了一個資料框hair.eye
aes()
中我們添加了參數frame=period
用於動態顯示gg
ggplotly
變成互動式圖表= inner_join(D2, outlooks[1:18,-3]) %>%
gg group_by(period, hair, eye) %>% summarise(
n = n(), bad=mean(align=="Bad"), female=mean(sex=="Female"),
dead=mean(alive=="Deceased"), .groups='drop') %>%
mutate(hair.eye = paste(hair,eye,sep=".")) %>%
ggplot(aes(bad, dead, label=hair.eye)) +
scale_color_gradientn(colors=c("seagreen","gold","red")) +
scale_size_continuous(range=c(2,12)) +
geom_point(aes(col=female, size=n, frame=period), alpha=0.8)
Joining, by = c("eye", "hair")
Warning: Ignoring unknown aesthetics: frame
ggplotly(gg) %>% animation_opts(100)
按左下角的“播放”按鈕,看看會發生什麼。 如果單獨移動滑桿,我們會發現大部分時間、大多數泡泡都聚集在一個區域。但是這些區域的位置、形狀和顏色會隨著時間變化,例如:(a)在2000年期間,我們看到紅色氣泡明顯低於綠色氣泡,這表示男性角色的傷亡率更高;(b)在1990 年,dead
似乎與bad
呈負相關,這意味著壞角色比好角色傷亡率低。
除了群體現象,我們還可以追踪每個氣泡,看看它的陣營、性別和死亡率是如何隨時間變化的。例如,no-hair.green-eyes
大多數情況下是男性和壞人,但它們的數量(泡泡大小)和死亡率在 30 年內發生了很大變化。
從社會學的觀點,上述現象和趨勢都可以算是重要的發現,但傳統的數學模型中很難出這些資訊,這種探索能力正是動態、互動式圖表最重要的價值。