《ggplot2:資料分析與圖形藝術》
第4章 用圖形建構圖像
4.6 幾何對象
幾何圖形對象,簡稱為geom,它執行着圖層的實際渲染,控制着生成的圖像類型。表4.2列出了ggplot2裡面所有可用的幾何對象。
- 表4.2 ggplot2中的幾何對象
名稱 | 描述 |
---|---|
abline | 線,由斜率和截距決定 |
area | 面積圖(area plot) |
bar | 條形圖,以x軸為底的矩形 |
bin2d | 2維熱圖 |
blank | 空白,什麼也不畫 |
boxplot | 箱線圖 |
contour | 等高線圖 |
crossbar | 帶有水準中心線的盒子圖 |
density | 光滑密度曲線圖 |
density2d | 二維密度等高線圖 |
dotplot | “點直方圖”,用點來表示觀測值的個數 |
errorbar | 誤差棒 |
errorbarh | 水準的誤差棒 |
freqploy | 頻率多邊形圖 |
hex | 用六邊形表示的2維熱圖 |
histogram | 直方圖 |
hline | 水準線 |
jitter | 給點添加擾動,減輕圖形重疊問題 |
line | 線圖,按照x坐标點大小順序依次連接配接各個觀測值 |
linerange | 一條代表一個區間的豎直線 |
map | 基準地圖裡的多邊形 |
path | 按資料的原始順序連接配接各個觀測值 |
point | 點,用來繪制散點圖 |
pointrange | 用一條中間帶點的豎直線代表一個區間 |
ploygon | 多邊形,相當于一個有填充的路徑 |
quantile | 添加分位數回歸線 |
raster | 高效的矩形瓦片圖 |
rect | 2維的矩形圖 |
ribbon | 色帶圖,連接配接的x值所對應的y的範圍 |
rug | 邊際地毯圖 |
segment | 添加線段或箭頭 |
smooth | 添加光滑的條件均值線 |
step | 以階梯形式連接配接各個觀測值 |
text | 文本注釋 |
tile | 瓦片圖 |
violin | 小提琴圖 |
vline | 豎直線 |
每個幾何對象都有一組它能識别的圖形屬性和一組繪圖所需的值。例如,一個點含有顔色、大小和形狀等圖形屬性,以及x和y位置坐标。一個條形含有高度、條寬、邊界顔色和填充顔色等圖形屬性值。表4.3列出了所有幾何對象的圖形屬性值。
- 表4.3預設的統計變換和圖形屬性。黑體圖形屬性是必須聲明的參數。
名稱 | 預設的統計變換 | 圖形屬性 |
---|---|---|
abline | abline | colour, linetype, size |
area | identity | colour, fill, linetype, size, x, y |
bar | bin | colour, fill, linetype, size, weight, x |
bin2d | bin2d | colour, fill, linetype, size, weight, xmax, xmin, ymax, ymin |
blank | identity | |
boxplot | boxplot | colour, fill, lower, middle, size, upper, weight, x, ymax, ymin |
contour | contour | colour, linetype, size, weight, x, y |
crossbar | identity | colour, fill, linetype, size, x, y, ymax, ymin |
density | density | colour, fill, linetype, size, weight, x, y |
density2d | density2d | colour, linetype, size, weight, x, y |
dotplot | dotplot | colour, fill, x, y |
errorbar | identity | colour, linetype, size, width, x, ymax, ymin |
errorbarh | identity | colour, linetype, size, width, y, ymax, ymin |
freqploy | bin | colour, linetype, size |
hex | binhex | colour, fill, size, x, y |
histogram | bin | colour, fill, linetype, size, weight, x |
hline | hline | colour, linetype, size |
jitter | identity | colour, fill, shape, size, x, y |
line | identity | colour, linetype, size, x, y |
linerange | identity | colour, linetype, size, x, ymax, ymin |
map | identity | colour, fill, linetype, size, x, y, map_id |
path | identity | colour, linetype, size, x, y |
point | identity | colour, fill, shape, size, x, y |
pointrange | identity | colour, fill, linetype, shape, size, x, y, ymax, ymin |
polygon | identity | colour, fill, linetype, size, x, y |
quantile | quantile | colour, linetype, size, weight, x, y |
raster | identity | colour, fill, linetype, size, x, y |
rect | identity | colour, fill, linetype, size, xmax, xmin, ymax, ymin |
ribbon | identity | colour, fill, linetype, size, x, ymax, ymin |
rug | identity | colour, linetype, size |
segment | identity | colour, linetype, size, x, xend, y, yend |
smooth | smooth | alpha, colour, fill, linetype, size, weight, x, y |
step | identity | colour, linetype, size, x, y |
text | identity | angle, colour, hjust, label, size, vjust, x, y |
tile | identity | colour, fill, linetype, size, x, y |
violin | ydensity | weight, colour, fill, size, linetype, x, y |
vline | vline | colour, linetype, size |
有些幾何對象主要在它們參數化的方式上有所不同。例如,瓦塊幾何對象(tile geom)設定的是其中心位置、長和寬,而矩形幾何對象(rect geom) 設定的是它的上(ymax)、下(ymin)、左(xmin)和右(right)位置。實際上,矩形幾何對象被看作一個多邊形,它的參數是四個角的位置。這在非笛卡爾坐标系中是非常有用的,在第7章我們會詳細介紹。
每一個幾何對象都有一個預設的統計變換,并且每一個統計變換都有一個預設的幾何對象。例如封箱(bin)統計變換預設使用條狀幾何對象(bar geom)來繪制直方圖。這些預設值可參見表4.3。修改這些預設值雖然能生成符合文法的繪圖,但是它們可能會違反一些繪圖慣例。見4.9.1節中的例子。
4.7 統計變換
統計變換,簡稱為stat,即對資料進行統計變換,它通常以某種方式對資料資訊進行彙總。例如,平滑(smoother)是一個很有用的統計變換,它能在一些限制條件的限制下計算給定x值時y的平均值。表4.4列出來目前可用的統計變換。為了闡明在圖形中的意義,一個統計變換必須時一個位置尺度不變量,即f(x+a)=f(x)+a并且f(b·x)=b·f(x)。這樣才能保證當改變圖形的标度時,資料變換保持不變。
用法是stat_bin(),stat_bin2() … …
- 表4.4 ggplot2中的統計變換
名稱 | 描述 |
---|---|
bin | 計算封箱(bin)資料 |
bin2d | 計算矩陣封箱内的觀測值個數 |
bindot | 計算“點直方圖”的封箱資料 |
binhex | 計算六邊形熱圖的封箱資料 |
boxplot | 計算組成箱線圖的各種元素值 |
contour | 三維資料的等高線 |
density | 一維密度估計 |
density2d | 二維密度估計 |
function | 添加新函數 |
identity | 不對資料進行統計變換 |
計算qq圖的相關值 | |
quantile | 計算連續的分位數 |
smooth | 添加光滑曲線 |
spoke | 将角度和半徑轉換成xend和yend |
sum | 計算每個單一值的頻數,有助于解決散點圖的圖形重疊問題 |
summary | 對每個x所對應的y值做統計描述 |
summary2d | 對2維矩陣封箱設定函數 |
summaryhex | 對2維六邊形封箱設定函數 |
unique | 删除重複值 |
ydensity | 小提琴圖,計算1維y軸方向的核密度函數估計值 |
統計變換可以将輸入的資料集看作輸入,将傳回的資料集作為輸出,是以統計變換可以向原資料集中插入新的變量。例如,常被用來繪制直方圖的stat_bin統計變換會生成如下變量:
count,每個組裡觀測值的數目;
density,每個組裡觀測值的密度(占整體的百分數/組寬);
x,組的中心位置。
這些生成變量可以被直接調用。例如,直方圖預設将條形的高度指派為觀測值的頻數(count),如果你更喜歡傳統的直方圖,可以用密度(density)來代替。例如:
> ggplot(diamonds, aes(carat))+geom_histogram(aes(y=..density..), binwidth=0.1)
#這時縱坐标的名稱為density
> ggplot(diamonds, aes(carat))+geom_histogram(aes(y=..count..), binwidth=0.1)
#這時縱坐标的名稱為count
生成的變量的名字必須要用“…”圍起來。可以防止原資料集中的變量和生成變量重名時造成混淆。
> qplot(carat, ..density.., data=diamonds, geom="histogram", binwidth=0.1)+ylab("density")
#用qplot函數,需要加一個ylab,否則生成的圖形的y軸,名稱為“…density…”。
4.8 位置調整
所謂位置調整,即對該層中的元素位置進行微調,簡稱為position。ggplot2中可用的位置調整參數:
- 表4.5五種位置調整參數
名稱 | 描述 |
---|---|
dodge | 避免重疊,并排放置 |
fill | 堆疊圖形元素并将高度标準化為1 |
identity | 不做任何調整 |
jitter | 給點添加擾動避免重合 |
stack | 将圖形元素堆疊起來 |
位置調整一般多見于處理離散型資料,連續型資料一般很少出現完全重疊的問題,當出現了這類問題時(由于資料密度高),即使微調,如随機擾動,通常也無法解決問題。
條形圖比較适合不同類型的位置調整,例如堆疊(stacking)、填充(filling)、并列(dodging)這三種類型。
堆疊式條形圖
> ggplot(diamonds, aes(clarity, fill=cut))+geom_bar()
這裡繪制的條形圖,屬于堆疊式條形圖(也是預設繪制圖形的結果),這裡x軸的表示clarity資料,而y軸表示計算x軸資料得到計算數量,是以用count表示。fill=cut,用cut進行圖形填充并分組,堆積的效果是不同x軸數值其對應的不同cut分組,每個x軸數值都對應着幾種cut的分組,對x軸的每一個值的同一類型cut的分組分别計數,之後将計算不同分組(不同顔色的條形長度)依次向上堆積。因為clarity(用于做x軸的分組)和cut(用于做資料填充顔色的分組)資料均屬于離散型變量,是以沒有出現圖形顔色遮擋的效果。
而如果指定y軸的值,則需要進行位置調整,否則繪圖失敗,例如:
> ggplot(diamonds, aes(x=clarity, y=table, fill=cut))+geom_bar()
錯誤: stat_count() must not be used with a y aesthetic.
這裡設定x軸的值為x=clarity,設定y軸的值為y=table。但會運作報錯,表示隻運用一個y軸的值顯示。
普通加y軸條形圖
是以在指定y軸的值後,必須加入位置調整參數,例如:
> ggplot(diamonds, aes(x=clarity, y=table, fill=cut))+geom_bar(position="identity", stat="identity")
#位置調整設定為不做任何調整(position=“identity”),統計變換stat也不做任何調整(stat=“identity”),
這樣y軸的值就顯示出來了,對應y軸顯示的數值,下面有執行個體解釋。
> test <- data.frame(type=c('A','B','C','A','A','B','B','C','C'), number=c(1,3,3,2,3,2,1,1,3), color=c('r','r','b','r','y','b','r','y','b'))
> test
·type number color
1 A 1 r
2 B 3 r
3 C 3 b
4 A 2 r
5 A 3 y
6 B 2 b
7 B 1 r
8 C 1 y
9 C 3 b
> ggplot(test, aes(type, number, fill=color))+geom_bar(position="identity", stat="identity")
#
根據上圖中值出現的位置
> subset(test, type=="A")
·type number color
1 A 1 r
4 A 2 r
5 A 3 y
#type為A時,A的r出現了1,2兩個數值,但被A的y出現的3這個值給覆寫了,是以條形值覆寫的順序是由rownames值的順序以此進行覆寫,即1,4,5。
> subset(test, type=="B")
·type number color
2 B 3 r
6 B 2 b
7 B 1 r
#type為B時,B的r先出現了3,之後B的b出現了2,最後B的r出現了1,是以按照2,6,7的覆寫順序得到了上述結果。
> subset(test, type=="C")
·type number color
3 C 3 b
8 C 1 y
9 C 3 b
type為C時,展示的結果和type為A時相同,都是被C的b給覆寫了,其number值為3最大。
是以對于geom_bar(position="
identity
", stat=“identity”)繪制的覆寫條形圖,圖形的覆寫順序是,對于某一個x軸的分類,fill填充的順序是按照其rownames出現的順序進行填充,如果rownames後面的數值其對應的y軸數值大,則會将前面的數值小的條形圖進行覆寫,是以柱形的柱頂顯示的值是x軸每一分類的最大值,不區分細分的fill分類。
> subset(test, type=="A")
·type number color
1 A 3 y
4 A 2 b
5 A 1 r
這樣覆寫的結果是y,b,r。
堆疊條形圖加y軸計數
y軸含數值的數量堆疊圖,需要用到堆疊的位置調整,例如:
> options(scipen=200)
#輸入這個指令後縱坐标軸不顯示科學計數法
> ggplot(diamonds, aes(x=clarity, y=table, fill=cut))+geom_bar(position="stack", stat="identity")
#位置調整設定為堆疊(position=“stack”),統計變換stat也不做任何調整(stat=“identity”),
這樣y軸的值就顯示出來了,對應y軸顯示的數值,下面有執行個體解釋。
> test <- data.frame(type=c('A','B','C','A','A','B','B','C','C'), number=c(1,3,3,2,3,2,1,1,3), color=c('r','r','b','r','y','b','r','y','b'))
> test
·type number color
1 A 1 r
2 B 3 r
3 C 3 b
4 A 2 r
5 A 3 y
6 B 2 b
7 B 1 r
8 C 1 y
9 C 3 b
> ggplot(test, aes(type, number, fill=color))+geom_bar(position="stack", stat="identity")
#
根據上圖中值出現的位置
> subset(test, type=="A")
·type number color
1 A 1 r
4 A 2 r
5 A 3 y
#type為A的r出現的number數值分别為1,2其加和為3,y出現的number數值為3,與r的加和數值相等,是以在圖中r和y的number數值加和為6,r和y的占比各0.5。
> subset(test, type=="B")
·type number color
2 B 3 r
6 B 2 b
7 B 1 r
#r的number值加和為4,b的number值為2,是以r占4,b占2,加和為6。
> subset(test, type=="C")
·type number color
3 C 3 b
8 C 1 y
9 C 3 b
#b加和為6,y為1,加和為7
是以對于geom_bar(position="
stack
", stat=“identity”)繪制的堆疊條形圖,在圖形中對于各個x軸的分類來說,其每一個fill分類都會進行顯示,柱形的最高值為各個fill分類的加和值,占比是看各個fill分類,相同分類的y軸數值加和再進行的占比計算,繪制最終占比結果。
填充式條形圖
> dds <- diamonds[sample(nrow(diamonds), 10), ]
#展示資料的存在樣式,我們隻随機選擇diamonds資料集的10個,并進行繪圖。
> dds
# A tibble: 10 x 10
carat cut color clarity depth table price x y
1 0.41 Premi… D VVS2 62.5 58 1295 4.72 4.75
2 0.9 Very … E SI1 61.8 60 4054 6.14 6.2
3 0.3 Very … E VVS2 61.4 58 789 4.25 4.28
4 0.3 Ideal H VS1 61.6 55 526 4.27 4.3
5 0.42 Very … D SI2 63.2 57 838 4.77 4.75
6 0.3 Good I SI1 64.1 57 391 4.25 4.3
7 1.02 Good E SI1 63.2 61 5183 6.31 6.37
8 0.39 Premi… E SI1 59.1 59 860 4.81 4.76
9 1.03 Ideal H SI1 62.2 56 5005 6.45 6.51
10 1.51 Very … H VVS2 63.1 59 11934 7.28 7.26
# ... with 1 more variable: z <dbl>
> ggplot(dds, aes(clarity, table, fill=color))+geom_bar(position="fill", stat="identity")
#我們首先看看資料集
> dds$clarity
#例如SI1存在兩個
[1] VS2 SI1 SI2 IF VVS2 VS1 SI2 VS1 SI2 SI1
8 Levels: I1 < SI2 < SI1 < VS2 < VS1 < VVS2 < … < IF
> dds$table
#對應的table的數值分别是56和63
[1] 60 56 60 57 56 60 60 57 62 63
> dds$color
#對應的color的分組為E和F兩種顔色
[1] G E F I H F D D J F
Levels: D < E < F < G < H < I < J
是以,在繪圖時position=“fill”, stat=“identity”,position表示位置調整,調整為fill,填充圖形元素并将高度标準化為1;stat表示統計變換,調整為identity,不做任何調整
這裡以clarity資料的SI1為例,在clarity中出現兩次,在table對應兩個數值56和63,在color對應兩種分類E和F;是以繪制的圖形高度标準化為1後,看的是table數值中各個值的占比,總比例為1,是以63大于56,而對應的顔色{E:56, F:63},對應的顔色條填充的占比也是F大于E,F的占比大于0.5,E的占比小于0.5,是以這是對該圖形較好的解釋,那種隻有一個數值或隻有一種顔色的占比值就為1。
是以對于geom_bar(position="
fill
", stat=“identity”)繪制的填充條形圖,在圖形中對于各個x軸的分類來說,其每一個fill分類都會進行顯示,柱形的最高值為1,填充圖的目的在于看占比,是以各個fill分類加和占比為1,占比值是看各個fill分類,相同分類的y軸數值加和再進行的占比計算,繪制最終占比結果,雖然不同x軸組别的y軸值加和不同,但最終柱形的值都為1,是以填充條形圖意在看占比結果。
> ggplot(test, aes(type, number, fill=color))+geom_bar(position="fill", stat="identity")
> subset(test, type=='A')
·type number color
1 A 1 r
4 A 2 r
5 A 3 y
> subset(test, type=='B')
·type number color
2 B 1 r
6 B 2 b
7 B 1 r
雖然,A的總number數為6與B的總number數為4不等,但在圖形中,A組的r與y占比各0.5,B組的r與b占比各0.5。
并列式條形圖
> test <- data.frame(type=c('A','B','C','A','A','B','B','C','C'), number=c(1,3,3,2,3,2,1,1,3), color=c('r','r','b','r','y','b','r','y','b'))
#先編造一定資料
> test
·type number color
1 A 1 r
2 B 3 r
3 C 3 b
4 A 2 r
5 A 3 y
6 B 2 b
7 B 1 r
8 C 1 y
9 C 3 b
> ggplot(test, aes(type, number, fill=color))+geom_bar(position="dodge", stat="identity")
#繪圖并看結果
解釋繪圖原因,并剖析;
首先繪制的結果是并列條形圖,position=“dodge”, stat=“identity”,position表示位置調整,調整為dodge,避免重疊,并排放置。并排放置條形圖後,條的高度取決于哪些結果呢,我們先看資料,以B為例,
2 B 3 r
;
6 B 2 b
;
7 B 1 r
;這裡同時出現了B3r和B1r,但是在圖中隻繪制了B3r的結果,是以同一個type的同一個color條圖的高度取決于number值的最大值。
如果是下面的資料
> test <- data.frame(type=c('A','B','C','A','A','B','B','C','C'), number=c(1,1,3,2,3,2,1,1,3), color=c('r','r','b','r','y','b','r','y','b'))
> subset(test, type=='B')
·type number color
2 B 1 r
6 B 2 b
7 B 1 r
B的b值為2,B的r值為1,則繪制的并列條形圖,B的r值為1。
是以對于geom_bar(position="
dodge
", stat=“identity”)繪制的并列條形圖,在圖形中對于各個x軸的分類來說,其每一個fill分類都會進行并行顯示,柱形的最高值為各個fill分類的最大值,注意這裡是最大值,并列圖顯示的規則是,将各個fill分類并行顯示之後,按照各個fill分類的y軸值進行覆寫,是以最終顯示的柱形的最高值為各個fill分類的最大值。
如果用直方圖繪制連續型資料,而且存在資料重疊問題,可将直方圖轉換為密度圖,這樣重疊的資料就都會顯示了。
> ggplot(diamonds, aes(clarity, color=cut))+geom_density()
或者将資料的count值計算出來作為權重值繪制線條圖。
4.9 整合
多種圖層的組合
4.9.1 結合幾何對象和統計變換
将幾何對象和不同的統計變換進行組合,繪制直方圖的三個“變體”。它們都應用了基于直方圖的統計變換,但使用了不同的幾何對象來展示結果:面積、點和瓦塊(tile)。
> d <- ggplot(diamonds, aes(carat))+xlim(0,3)
> d + stat_bin(aes(ymax=..count..), binwidth=0.1, geom="area")
#stat_bin表示計算封箱(bin)資料
> d + stat_bin(aes(size=..density..), binwidth=0.1, geom="point", position="identity")
> d + stat_bin2d(aes(y=1, fill=..count..), binwidth=0.1, geom="tile", position="identity")
#如果用stat_bin()則會報錯
錯誤: stat_bin() must not be used with a y aesthetic.
;stat_bin表明統計變換是計數,計數會被投射到y軸,與y=1沖突。
上面展示的是直方圖的三種變體,即頻率多邊形;散點圖,點的大小和高度都映射給了頻率;熱圖用顔色來表示頻率。
類似地,ggplot2中有大量的幾何對象是基于其他幾何對象衍生出來的,即修改某個已經存在的幾何對象的預設圖形屬性或統計變換。例如,擾動幾何對象(jitter geom)就是将點的位置調整設定為随機打亂。當某種圖形變體被多次使用,或者在某種非常特殊的環境下使用時,你便可以建立一個新的幾何對象。表4.6列出了一些幾何對象的“别名”。
- 表4.6通過修改其他幾何對象預設值得到的幾何對象
别稱 | 基礎幾何對象 | 預設值的更改 |
---|---|---|
area | ribbon | aes(min=0, max=y), position=“stack” |
density | area | stat=“density” |
freqpoly | line | stat=“bin” |
histogram | bar | stat=“bin” |
jitter | point | position=“jitter” |
quantile | line | stat=“quantile” |
smooth | ribbon | stat=“smooth” |
4.9.2 顯示已計算過的統計量
如果你有已經彙總過的資料,并且想直接用它,而不進行其他的統計變換,可以使用stat_identity(),然後将合适的變量映射到相應的圖形屬性中。