《R語言實戰》學習筆記 -- 第六章 基本圖形

條形圖

條形圖通過垂直的或水平的條形展示了類別型變量的分布(頻數)。函數 barplot() 的最簡單用法是:

barplot(height)

其中的 height 是一個向量或一個矩陣。

在接下來的示例中,我們將繪制一項探索類風濕性關節炎新療法研究的結果。數據已包含在隨 vcd 包分發的 Arthritis 數據框中。由于 vcd 包并沒用包括在R的默認安裝中,請確保在第一次使用之前先安裝它:

install. packages("vcd") 

注意,我們并不需要使用 vcd 包來創建條形圖。我們讀入它的原因是為了使用 Arthritis 數據集。但我們需要使用 vcd 包創建6.1.5節中描述的棘狀圖(spinogram)。

簡單的條形圖

library(vcd)
pdf("test1.pdf")
counts <- table(Arthritis$Improved)
par(mfrow=c(1,2))
barplot(counts,
        main="Simple Bar Plot",
        xlab="Improvement", ylab="Frequency")
barplot(counts,
        main="Horizontal Bar Plot",
        xlab="Frequency", ylab="Improvement",
        horiz=TRUE)
dev.off()

horiz=TRUE則會生成一幅水平條形圖

如果標簽很長怎么辦?在6.1.4節中,你將看到微調標簽的方法,這樣它們就不會重疊了。

堆砌條形圖和分組條形圖

如果 height 是一個矩陣而不是一個向量,則繪圖結果將是一幅堆砌條形圖或分組條形圖。若 beside=FALSE (默認值),則矩陣中的每一列都將生成圖中的一個條形,各列中的值將給出堆砌的“子條”的高度。若 beside=TRUE ,則矩陣中的每一列都表示一個分組,各列中的值將并列而不是堆砌。

考慮治療類型和改善情況的列聯表:

> counts <- table(Arthritis$Improved, Arthritis$Treatment)
> counts
        
         Placebo Treated
  None        29      13
  Some         7       7
  Marked       7      21

你可以將此結果繪制為一幅堆砌條形圖或一幅分組條形圖(見代碼清單6-2)。結果如圖6-2
所示。

# 堆砌條形圖
barplot(counts,
        main="Stacked Bar Plot",
        xlab="Treatment", ylab="Frequency",
        col=c("red", "yellow","green"),
        legend=rownames(counts))
# 分組條形圖
barplot(counts,
        main="Grouped Bar Plot",
        xlab="Treatment", ylab="Frequency",
        col=c("red", "yellow", "green"),
        legend=rownames(counts), beside=TRUE)

在第3章中,我們講解過格式化和放置圖例的方法,以確保最好的效果。請試著重新排布圖例的位置以避免它們和條形產生疊加。

# 修改一下Y軸的范圍即可
pdf("test1.pdf")
counts <- table(Arthritis$Improved, Arthritis$Treatment)
counts
par(mfrow=c(1,2))
x = c(0,10,20,30,40,50,60)
# 堆砌條形圖
barplot(counts,
        main="Stacked Bar Plot",
        xlab="Treatment", ylab="Frequency",
        col=c("red", "yellow","green"),
        legend=rownames(counts),
        ylim = c(0, 60))
# 分組條形圖
barplot(counts,
        main="Grouped Bar Plot",
        xlab="Treatment", ylab="Frequency",
        col=c("red", "yellow", "green"),
        legend=rownames(counts), beside=TRUE,
        ylim = c(0, 40))
dev.off()

均值條形圖

條形圖并不一定要基于計數數據或頻率數據。你可以使用數據整合函數并將結果傳遞給barplot() 函數,來創建表示均值、中位數、標準差等的條形圖。代碼清單6-3展示了一個示例,結果如圖6-3所示。

> states <- data.frame(state.region, state.x77)
> states
                state.region Population Income Illiteracy Life.Exp Murder HS.Grad Frost   Area
Alabama                South       3615   3624        2.1    69.05   15.1    41.3    20  50708
Alaska                  West        365   6315        1.5    69.31   11.3    66.7   152 566432
Arizona                 West       2212   4530        1.8    70.55    7.8    58.1    15 113417
Arkansas               South       2110   3378        1.9    70.66   10.1    39.9    65  51945
California              West      21198   5114        1.1    71.71   10.3    62.6    20 156361
Colorado                West       2541   4884        0.7    72.06    6.8    63.9   166 103766
Connecticut        Northeast       3100   5348        1.1    72.48    3.1    56.0   139   4862
Delaware               South        579   4809        0.9    70.06    6.2    54.6   103   1982
Florida                South       8277   4815        1.3    70.66   10.7    52.6    11  54090
Georgia                South       4931   4091        2.0    68.54   13.9    40.6    60  58073
Hawaii                  West        868   4963        1.9    73.60    6.2    61.9     0   6425
Idaho                   West        813   4119        0.6    71.87    5.3    59.5   126  82677
Illinois       North Central      11197   5107        0.9    70.14   10.3    52.6   127  55748
Indiana        North Central       5313   4458        0.7    70.88    7.1    52.9   122  36097
Iowa           North Central       2861   4628        0.5    72.56    2.3    59.0   140  55941
Kansas         North Central       2280   4669        0.6    72.58    4.5    59.9   114  81787
Kentucky               South       3387   3712        1.6    70.10   10.6    38.5    95  39650
Louisiana              South       3806   3545        2.8    68.76   13.2    42.2    12  44930
Maine              Northeast       1058   3694        0.7    70.39    2.7    54.7   161  30920
Maryland               South       4122   5299        0.9    70.22    8.5    52.3   101   9891
Massachusetts      Northeast       5814   4755        1.1    71.83    3.3    58.5   103   7826
Michigan       North Central       9111   4751        0.9    70.63   11.1    52.8   125  56817
Minnesota      North Central       3921   4675        0.6    72.96    2.3    57.6   160  79289
Mississippi            South       2341   3098        2.4    68.09   12.5    41.0    50  47296
Missouri       North Central       4767   4254        0.8    70.69    9.3    48.8   108  68995
Montana                 West        746   4347        0.6    70.56    5.0    59.2   155 145587
Nebraska       North Central       1544   4508        0.6    72.60    2.9    59.3   139  76483
Nevada                  West        590   5149        0.5    69.03   11.5    65.2   188 109889
New Hampshire      Northeast        812   4281        0.7    71.23    3.3    57.6   174   9027
New Jersey         Northeast       7333   5237        1.1    70.93    5.2    52.5   115   7521
New Mexico              West       1144   3601        2.2    70.32    9.7    55.2   120 121412
New York           Northeast      18076   4903        1.4    70.55   10.9    52.7    82  47831
North Carolina         South       5441   3875        1.8    69.21   11.1    38.5    80  48798
North Dakota   North Central        637   5087        0.8    72.78    1.4    50.3   186  69273
Ohio           North Central      10735   4561        0.8    70.82    7.4    53.2   124  40975
Oklahoma               South       2715   3983        1.1    71.42    6.4    51.6    82  68782
Oregon                  West       2284   4660        0.6    72.13    4.2    60.0    44  96184
Pennsylvania       Northeast      11860   4449        1.0    70.43    6.1    50.2   126  44966
Rhode Island       Northeast        931   4558        1.3    71.90    2.4    46.4   127   1049
South Carolina         South       2816   3635        2.3    67.96   11.6    37.8    65  30225
South Dakota   North Central        681   4167        0.5    72.08    1.7    53.3   172  75955
Tennessee              South       4173   3821        1.7    70.11   11.0    41.8    70  41328
Texas                  South      12237   4188        2.2    70.90   12.2    47.4    35 262134
Utah                    West       1203   4022        0.6    72.90    4.5    67.3   137  82096
Vermont            Northeast        472   3907        0.6    71.64    5.5    57.1   168   9267
Virginia               South       4981   4701        1.4    70.08    9.5    47.8    85  39780
Washington              West       3559   4864        0.6    71.72    4.3    63.5    32  66570
West Virginia          South       1799   3617        1.4    69.48    6.7    41.6   100  24070
Wisconsin      North Central       4589   4468        0.7    72.48    3.0    54.5   149  54464
Wyoming                 West        376   4566        0.6    70.29    6.9    62.9   173  97203
# aggregate()函數的使用方法見第五章——數據的整合與重構
> means <- aggregate(states$Illiteracy, by=list(state.region), FUN=mean)
> means
        Group.1        x
1     Northeast 1.000000
2         South 1.737500
3 North Central 0.700000
4          West 1.023077
barplot(means$x, names.arg=means$Group.1,
        col = "Blue")
title("Mean Illiteracy Rate")
美國各地區平均文盲率排序的條形圖

means$x 是包含各條形高度的向量,而添加選項 names.arg=means$Group.1是為了展示標簽。

條形圖的微調

有若干種方式可以微調條形圖的外觀。例如,隨著條數的增多,條形的標簽可能會開始重疊。你可以使用參數 cex.names 來減小字號。將其指定為小于1的值可以縮小標簽的大小??蛇x的參數 names.arg 允許你指定一個字符向量作為條形的標簽名。你同樣可以使用圖形參數輔助調整文本間隔。

代碼清單6-4給出了一個示例,輸出如圖6-4所示。

par(mar=c(5,8,4,2))
par(las=2)
counts <- table(Arthritis$Improved)
barplot(counts,
main="Treatment Outcome",
horiz=TRUE,
cex.names=0.8,
names.arg=c("No Improvement", "Some Improvement",
"Marked Improvement"))

par() 函數能夠讓你對R的默認圖形做出大量修改。詳情參閱第3章。

棘狀圖

在結束關于條形圖的討論之前,讓我們再來看一種特殊的條形圖,它稱為棘狀圖(spinogram)。棘狀圖對堆砌條形圖進行了重縮放,這樣每個條形的高度均為1,每一段的高度即表示比例。棘狀圖可由 vcd 包中的函數 spine() 繪制。以下代碼可以生成一幅簡單的棘狀圖:

library(vcd)
attach(Arthritis)
counts <- table(Treatment, Improved)
spine(counts, main="Spinogram Example")
detach(Arthritis)

輸出如圖6-5所示。治療組同安慰劑組相比,獲得顯著改善的患者比例明顯更高。

餅圖

餅圖可由以下函數創建:

pie(x, labels)

其中 x 是一個非負數值向量,表示每個扇形的面積,而 labels 則是表示各扇形標簽的字符型向量。

代碼清單6-5給出了四個示例,結果如圖6-6所示。

par(mfrow=c(2, 2))
slices <- c(10, 12,4, 16, 8)
lbls <- c("US", "UK", "Australia", "Germany", "France")

pie(slices, labels = lbls,
    main="Simple Pie Chart")
pct <- round(slices/sum(slices)*100)
lbls2 <- paste(lbls, " ", pct, "%", sep="")

pie(slices, labels=lbls2, col=rainbow(length(lbls2)),
    main="Pie Chart with Percentages")
library(plotrix)

pie3D(slices, labels=lbls,explode=0.1,
      main="3D Pie Chart ")
mytable <- table(state.region)
lbls3 <- paste(names(mytable), "\n", mytable, sep="")

pie(mytable, labels = lbls3,
    main="Pie Chart from a Table\n (with sample sizes)")

其中 x 是一個非負數值向量,表示每個扇形的面積,而 labels 則是表示各扇形標簽的字符型向量。

代碼清單6-5給出了四個示例,結果如圖6-6所示。

餅圖讓比較各扇形的值變得困難(除非這些值被附加在標簽上)。例如,觀察(第一幅)最簡單的餅圖,你能分辨出美國(US)和德國(Germany)的大小嗎?(如果你可以,說明你的洞察力比我好。)為改善這種狀況,我們創造了一種稱為扇形圖(fan plot)的餅圖變種。扇形圖(Lemon& Tyagi,2009)提供了一種同時展示相對數量和相互差異的方法。在R中,扇形圖是通過 plotrix包中的 fan.plot() 函數實現的。

考慮以下代碼和結果圖(圖6-7):

library(plotrix)
slices <- c(10, 12,4, 16, 8)
lbls <- c("US", "UK", "Australia", "Germany", "France")
fan.plot(slices, labels = lbls, main="Fan Plot")

如你所見,確定扇形圖中扇形的相對大小比餅圖要簡單得多。扇形圖雖然尚未普及,但它仍然是新生力量。

既然已經講完了餅圖和扇形圖,就讓我們轉到直方圖上吧。與條形圖和餅圖不同,直方圖描述的是連續型變量的分布。

直方圖

直方圖通過在x軸上將值域分割為一定數量的組,在y軸上顯示相應值的頻數,展示了連續型變量的分布??梢允褂萌缦潞瘮祫摻ㄖ狈綀D:

hist(x)

其中的 x 是一個由數據值組成的數值向量。參數 freq=FALSE 表示根據概率密度而不是頻數繪制圖形。參數 breaks 用于控制組的數量。在定義直方圖中的單元時,默認將生成等距切分。代碼

清單6-6提供了繪制四種直方圖的代碼,繪制結果見圖6-8。

par(mfrow=c(2,2))

hist(mtcars$mpg)

hist(mtcars$mpg,
    breaks=12,
    col="red",
    xlab="Miles Per Gallon",
    main="Colored histogram with 12 bins")

hist(mtcars$mpg,
    freq=FALSE,
    breaks=12,
    col="red",
    xlab="Miles Per Gallon",
    main="Histogram, rug plot, density curve")
    rug(jitter(mtcars$mpg))
lines(density(mtcars$mpg), col="blue", lwd=2)

x <- mtcars$mpg
h<-hist(x,
breaks=12,
col="red",
xlab="Miles Per Gallon",
main="Histogram with normal curve and box")
xfit<-seq(min(x), max(x), length=40)
yfit<-dnorm(xfit, mean=mean(x), sd=sd(x))
yfit <- yfit*diff(h$mids[1:2])*length(x)
lines(xfit, yfit, col="blue", lwd=2)
box()

核密度圖

在上節中,你看到了直方圖上疊加的核密度圖。用術語來說,核密度估計是用于估計隨機變量概率密度函數的一種非參數方法。雖然其數學細節已經超出了本書的范疇,但從總體上講,核密度圖不失為一種用來觀察連續型變量分布的有效方法。繪制密度圖的方法(不疊加到另一幅圖上方)為:

plot(density(x))

其中的 x 是一個數值型向量。由于 plot() 函數會創建一幅新的圖形,所以要向一幅已經存在的圖形上疊加一條密度曲線,可以使用 lines() 函數(如代碼清單6-6所示)

代碼清單6-7給出了兩幅核密度圖示例,結果如圖6-9所示。

par(mfrow=c(2,1))
d <- density(mtcars$mpg)
# 完全使用默認參數
plot(d)
d <- density(mtcars$mpg)
# 添加標題
plot(d, main="Kernel Density of Miles Per Gallon")
# 將曲線改為藍色,并使用實心紅色填充曲線下方的區域
polygon(d, col="red", border="blue")
# 添加棕色的軸須圖
rug(mtcars$mpg, col="brown")

箱線圖

箱線圖(又稱盒須圖)通過繪制連續型變量的五數總括,即最小值、下四分位數(第25百分位數)、中位數(第50百分位數)、上四分位數(第75百分位數)以及最大值,描述了連續型變量的分布。箱線圖能夠顯示出可能為離群點(范圍±1.5*IQR以外的值,IQR表示四分位距,即上四分位數與下四分位數的差值)的觀測。例如:

boxplot(mtcars$mpg, main="Box plot", ylab="Miles per Gallon")

生成了如圖6-11所示的圖形。為了圖解各個組成部分,我手工添加了標注。

默認情況下,兩條須的延伸極限不會超過盒型各端加1.5倍四分位距的范圍。此范圍以外的值將以點來表示(在這里沒有畫出)。

舉例來說,在我們的車型樣本中,每加侖汽油行駛英里數的中位數是19.2,50%的值都落在了15.3和22.8之間,最小值為10.4,最大值為33.9。我是如何從圖中如此精確地讀出了這些值呢?執行 boxplot.stats(mtcars$mpg) 即可輸出用于構建圖形的統計量(換句話說,我作弊了)。圖中似乎不存在離群點,而且略微正偏(上側的須較下側的須更長)。

使用并列箱線圖進行跨組比較

箱線圖可以展示單個變量或分組變量。使用格式為:

boxplot(formula, data=dataframe)

其中的 formula 是一個公式, dataframe 代表提供數據的數據框(或列表)。一個示例公式為 y ~A ,這將為類別型變量 A 的每個值并列地生成數值型變量 y 的箱線圖。公式 y ~ A*B 則將為類別型變量 A 和 B 所有水平的兩兩組合生成數值型變量 y 的箱線圖。添加參數 varwidth=TRUE 將使箱線圖的寬度與其樣本大小的平方根成正比。參數horizontal=TRUE 可以反轉坐標軸的方向。

在以下代碼中,我們使用并列箱線圖重新研究了四缸、六缸、八缸發動機對每加侖汽油行駛的英里數的影響。結果如圖6-12所示。

boxplot(mpg ~ cyl, data=mtcars,
        main="Car Mileage Data",
        xlab="Number of Cylinders",
        ylab="Miles Per Gallon")

在圖6-12中可以看到不同組間油耗的區別非常明顯。同時也可以發現,六缸車型的每加侖汽油行駛的英里數分布較其他兩類車型更為均勻。與六缸和八缸車型相比,四缸車型的每加侖汽油行駛的英里數散布最廣(且正偏)。在八缸組還有一個離群點。箱線圖靈活多變,通過添加 notch=TRUE ,可以得到含凹槽的箱線圖。若兩個箱的凹槽互不重疊,則表明它們的中位數有顯著差異(Chambers et al.,1983,p. 62)。以下代碼將為我們的車型油耗示例創建一幅含凹槽的箱線圖:

boxplot(mpg ~ cyl, data=mtcars,
        notch=TRUE,
        varwidth=TRUE,
        col="red",
        main="Car Mileage Data",
        xlab="Number of Cylinders",
        ylab="Miles Per Gallon")

參數 col 以紅色填充了箱線圖,而 varwidth=TRUE 則使箱線圖的寬度與它們各自的樣本大小成正比。

在圖6-13中可以看到,四缸、六缸、八缸車型的油耗中位數是不同的。隨著汽缸數的減少,油耗明顯降低。

最后,你可以為多個分組因子繪制箱線圖。代碼清單6-9為不同缸數和不同變速箱類型的車型繪制了每加侖汽油行駛英里數的箱線圖(圖形如圖6-14所示)。同樣地,這里使用參數 col 為箱線圖進行了著色。請注意顏色的循環使用。在本例中,共有六幅箱線圖和兩種指定的顏色,所以顏色將重復使用三次。

mtcars$cyl.f <- factor(mtcars$cyl,
                       levels=c(4,6,8),
                       labels=c("4","6","8"))
mtcars$am.f <- factor(mtcars$am,
                      levels=c(0,1),
                      labels=c("auto", "standard"))
boxplot(mpg ~ am.f *cyl.f,
        data=mtcars,
        varwidth=TRUE,
        col=c("gold","darkgreen"),
        main="MPG Distribution by Auto Type",
        xlab="Auto Type", ylab="Miles Per Gallon")

圖6-14再一次清晰地顯示出油耗隨著缸數的下降而減少。對于四缸和六缸車型,標準變速箱(standard)的油耗更高。但是對于八缸車型,油耗似乎沒有差別。你也可以從箱線圖的寬度看出,四缸標準變速箱的車型和八缸自動變速箱的車型在數據集中最常見。

小提琴圖

在結束箱線圖的討論之前,有必要研究一種稱為小提琴圖(violin plot)的箱線圖變種。小提琴圖是箱線圖與核密度圖的結合。你可以使用 vioplot 包中的 vioplot() 函數繪制它。請在第一次使用之前安裝 vioplot 包。
vioplot() 函數的使用格式為:

vioplot(x1, x2, ... , names=, col=)

其中 x1, x2, ... 表示要繪制的一個或多個數值向量(將為每個向量繪制一幅小提琴圖)。參數names 是小提琴圖中標簽的字符向量,而 col 是一個為每幅小提琴圖指定顏色的向量。代碼清單6-10中給出了一個示例。

library(vioplot)
x1 <- mtcars$mpg[mtcars$cyl==4]
x2 <- mtcars$mpg[mtcars$cyl==6]
x3 <- mtcars$mpg[mtcars$cyl==8]
vioplot(x1, x2, x3,
        names=c("4 cyl", "6 cyl", "8 cyl"),
        col="gold")
title("Violin Plots of Miles Per Gallon", ylab="Miles Per Gallon",
      xlab="Number of Cylinders")

小提琴圖基本上是核密度圖以鏡像方式在箱線圖上的疊加。在圖中,白點是中位數,黑色盒型的范圍是下四分位點到上四分位點,細黑線表示須。外部形狀即為核密度估計。小提琴圖還沒有真正地流行起來。同樣,這可能也是由于普遍缺乏方便好用的軟件導致的。時間會證明一切。我們將以點圖結束本章。與之前看到的圖形不同,點圖繪制變量中的所有值。

點圖

點圖提供了一種在簡單水平刻度上繪制大量有標簽值的方法。你可以使用 dotchart() 函數
創建點圖,格式為:

dotchart(x, labels=)

其中的 x 是一個數值向量,而 labels 則是由每個點的標簽組成的向量。你可以通過添加參數groups 來選定一個因子,用以指定 x 中元素的分組方式。如果這樣做,則參數 gcolor 可以控制不同組標簽的顏色, cex 可以控制標簽的大小。這里是 mtcars 數據集的一個示例:

dotchart(mtcars$mpg, labels=row.names(mtcars), cex=.7,
main="Gas Mileage for Car Models",
xlab="Miles Per Gallon")

繪圖結果已在圖6-16中給出。

圖6-16可以讓你在同一個水平軸上觀察每種車型的每加侖汽油行駛英里數。通常來說,點圖在經過排序并且分組變量被不同的符號和顏色區分開的時候最有用。代碼清單6-11給出了一個示例,繪圖的結果如圖6-17所示。

x <- mtcars[order(mtcars$mpg),]
x$cyl <- factor(x$cyl)
x$color[x$cyl==4] <- "red"
x$color[x$cyl==6] <- "blue"
x$color[x$cyl==8] <- "darkgreen"
dotchart(x$mpg,
         labels = row.names(x),
         cex=.7,
         groups = x$cyl,
         gcolor = "black",
         color = x$color,
         pch=19,
         main = "Gas Mileage for Car Models\ngrouped by cylinder",
         xlab = "Miles Per Gallon")

在圖6-17中,許多特征第一次明顯起來。你再次看到,隨著汽缸數的減少,每加侖汽油行駛的英里數有了增加。但你同時也看到了例外。例如,Pontiac Firebird有8個汽缸,但較六缸的Mercury280C和Valiant的行駛英里數更多。六缸的Hornet 4 Drive與四缸的Volvo 142E的每加侖汽油行駛英里數相同。同樣明顯的是,Toyota Corolla的油耗最低,而Lincoln Continental和Cadillac Fleetwood是英里數較低一端的離群點。

在本例中,你可以從點圖中獲得顯著的洞察力,因為每個點都有標簽,每個點的值都有其內在含義,并且這些點是以一種能夠促進比較的方式排布的。但是隨著數據點的增多,點圖的實用性隨之下降。

注意 點圖有許多變種。Jacoby(2006)對點圖進行了非常有意義的討論,并且提供了創新型應用的R代碼。此外, Hmisc 包也提供了一個帶有許多附加功能的點圖函數(恰如其分地叫作 dotchart2 )。


END !

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容