美文网首页R学习与可视化
《R语言实战》学习笔记 -- 第六章 基本图形

《R语言实战》学习笔记 -- 第六章 基本图形

作者: 生信摆渡 | 来源:发表于2019-12-24 19:42 被阅读0次

    条形图

    条形图通过垂直的或水平的条形展示了类别型变量的分布(频数)。函数 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的值可以缩小标签的大小。可选的参数 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轴上显示相应值的频数,展示了连续型变量的分布。可以使用如下函数创建直方图:

    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 !

    相关文章

      网友评论

        本文标题:《R语言实战》学习笔记 -- 第六章 基本图形

        本文链接:https://www.haomeiwen.com/subject/vmwfoctx.html