分享

R包介绍 || ggplot2包--R可视化(二)

 生物_医药_科研 2019-01-24

.4统计变换(statistics)

   统计变换是以某种方式对数据信息进行汇总,几何对象控制生成的图像类型。“一个几何对象包含了一种统计变换,一个统计变换包含了一个几何对象”这句话更准确地来说是“每一个几何对象都有一个默认的统计变换,并且每一个统计变换也都有一个默认的几何对象”。

  查看可用统计变换:

ls('package:ggplot2', pattern='^stat_.+')## [1] 'stat_bin'         'stat_bin_2d'      'stat_bin_hex'    ## [4] 'stat_bin2d'       'stat_binhex'      'stat_boxplot'    ## [7] 'stat_contour'     'stat_count'       'stat_density'    ## [10] 'stat_density_2d'  'stat_density2d'   'stat_ecdf'       ## [13] 'stat_ellipse'     'stat_function'    'stat_identity'   ## [16] 'stat_qq'          'stat_quantile'    'stat_smooth'     ## [19] 'stat_spoke'       'stat_sum'         'stat_summary'    ## [22] 'stat_summary_2d'  'stat_summary_bin' 'stat_summary_hex'## [25] 'stat_summary2d'   'stat_unique'      'stat_ydensity'

  举个例子来说明每一个几何对象都会有一个默认的统计变换。如果我们想要绘制ggplot2中的数据集diamonds中的carat直方图:

ggplot(diamonds,aes(carat))+geom_histogram(binwidth=0.1)

  

  这里geom_histogram意味着我们选择的几何对象是直方图,而绘制一个直方图就需要确定条形图的高度和组的中心值,所以必须要对数据进行统计变换,这里的统计变换包括count(观测值计数),density(观测值密度),x(组的中心位置),然后默认将条形图的高度赋值为观测值的频数(count),当然如果想要用密度代替也是可以的:

ggplot(diamonds,aes(carat))+geom_histogram(aes(y=..density..),binwidth=0.1)

  同样每个统计变换都有默认的几何对象,封箱(bin)统计变换默认使用条状几何对象(bar geom)来绘制直方图,下面的语句所绘制的图像和之前绘制的直方图是一样的。

ggplot(diamonds,aes(carat))+stat_bin(binwidth = 0.1)   ggplot(diamonds,aes(carat))+stat_bin(aes(y=..density..),binwidth = 0.1)

  既然是默认的统计变换/几何对象,那么是可以改变默认值的,这样会画出新奇甚至怪异的图像。
  我们把统计变换bin默认的几何对象”bar“改为”area“和”step“

ggplot(diamonds,aes(carat))+stat_bin(aes(ymax=..density..),binwidth = 0.1,geom='area')
ggplot(diamonds,aes(carat))+stat_bin(aes(ymax=..count..),binwidth = 0.1,geom='step')

  统计变换对原始数据进行某种计算,然后在图上表示出来,例如对散点图上加一条回归线。可以使用stat=来设定统计变换方式。

ggplot(newDiamonds, aes(x=carat, y=price))+geom_point()+scale_y_log10()+stat_smooth()

  这里就不按颜色、切工来分了,不然ggplot会按不同的分类变量分别做回归,图就很乱,如果我们需要这样做,我们可以使用分面,这个将在后面介绍。这里,aes所提供的参数,就通过ggplot提供,而不是提供给geom_point,因为ggplot里 的参数,相当于全局变量,geom_point()和stat_smooth()都知道x,y的映射,如果只提供给geom_point(),则相当于是 局部变量,geom_point知道这种映射,而stat_smooth不知道,当然你再给stat_smooth也提供x,y的映射,不过共用的映射, 还是提供给ggplot好。

  在ggplot2中,每种几何类型都有对应的(默认)统计类型,反之亦然,两者不分家,下面对二者进行组合说明:

  看一下几何函数geom_point和统计函数stat_identity的参数:

# 函数说明,非运行代码geom_point(mapping = NULL, data = NULL, stat = 'identity',           position = 'identity', na.rm = FALSE, ...)stat_identity(mapping = NULL, data = NULL, geom = 'point',              position = 'identity', width = NULL,              height = NULL, ...)

  有4个参数是一样的:映射(mapping)、数据(data)、位置(position)和点点点(Dot-dot-dot: …)。H.W.特别强调了mapping和data参数的先后顺序在几何/统计类型设定函数和ggplot函数中的差别:ggplot函数先设定数据,再 设定映射;而几何/统计类型函数则相反,因为确定作图或统计之前一般都已经有数据,只需指定映射即可。如果不写参数名,它们的用法是这样的:

# 示例,非运行代码ggplot(数据, 映射)geom_xxx(映射, 数据)stat_xxx(映射, 数据

'点点点'参数是R语言非常特殊的一个数据类型,用在函数的参数用表示任意参数,在这里表示传递给图层的任意参数如color, shape, alpha等。

前面我们一直用geom_point来做散点图,其实完全可以用stat_identity来做,得到的图形是完全相同的:

# 取ggplot2的diamonds数据集的一部分数据:set.seed(100)d.sub <- diamonds[sample(nrow(diamonds),="">500),]g <- ggplot(d.sub,="" aes(x="carat," y="">price))theme_set(theme_bw())g + stat_identity() + ggtitle('geom_identity()')g + geom_point() + ggtitle('geom_point()')

 

4.5坐标系统(coordinate)

   坐标系统控制坐标轴,可以进行变换,例如XY轴翻转,笛卡尔坐标和极坐标转换,以满足我们的各种需求。

   坐标轴翻转由coord_flip()实现:

ggplot(newDiamonds)+geom_bar(aes(x=cut, fill=cut))+coord_flip()

   而转换成极坐标可以由coord_polar()实现:

ggplot(newDiamonds)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar(theta='y')

   这也是为什么之前介绍常用图形画法时没有提及饼图的原因,饼图实际上就是柱状图,只不过是使用极坐标而已,柱状图的高度,对应于饼图的弧度,饼图并不推荐,因为人类的眼睛比较弧度的能力比不上比较高度(柱状图)

   还可以画靶心图:

ggplot(newDiamonds)+geom_bar(aes(x=factor(1), fill=cut))+coord_polar()

  以及风玫瑰图(windrose):

ggplot(newDiamonds)+geom_bar(aes(x=clarity, fill=cut))+coord_polar()head(newDiamonds)##       carat       cut color clarity depth table price    x    y    z## 49345  0.71 Very Good     H     SI1  62.5    60  2096 5.68 5.75 3.57## 50545  0.79   Premium     H     SI1  61.8    59  2275 5.97 5.91 3.67## 15434  1.03     Ideal     F     SI1  62.4    57  6178 6.48 6.44 4.03## 44792  0.50     Ideal     E     VS2  62.2    54  1624 5.08 5.11 3.17## 34614  0.27     Ideal     E     VS1  61.6    56   470 4.14 4.17 2.56## 27998  0.30   Premium     E     VS2  61.7    58   658 4.32 4.34 2.67

4.6图层(Layer)

4.6.1图层对象

  geom_xxx和stat_xxx可以指定数据,映射、几何类型和统计类型,一般来说,有这些东西我们就可以作图了。但实际情况是这些函数不可以直接出图,因为它不是完整的ggplot对象:

g <- geom_point(mapping="aes(x=carat," y="price)," data="">d.sub)class(g)## [1] 'LayerInstance' 'Layer'   'ggproto'g## mapping: x = carat, y = price ## geom_point: na.rm = FALSE## stat_identity: na.rm = FALSE## position_identity 

  图层只是存储类型为environment的R语言对象,它只有建立在ggplot结构的基础上才会成为图形,在这里哪怕是一个空的ggplot对象框架都很有用。这好比仓库里的帐篷,如果你找不到地方把它们支起来,这些东西顶多是一堆货物:

ggplot() + gclass(ggplot() + g)## [1] 'gg'  'ggplot'

  前面说过多个图层的相加是有顺序的,图层和ggplot对象的加法也是有顺序的,如果把ggplot对象加到图层上就没有意义。这种规则同样适用于映射和ggplot的相加:

g + ggplot()## NULLclass(aes(x=carat, y=price) + ggplot(d.sub))## [1] 'NULL'class(ggplot(d.sub) + aes(x=carat, y=price))## [1] 'gg'  'ggplot'

4.6.2图层的位置调整参数

当前版ggplot2常用的有5种:

  • dodge:“避让”方式,即往旁边闪,如柱形图的并排方式就是这种。

  • fill:填充方式, 先把数据归一化,再填充到绘图区的顶部。

  • identity:原地不动,不调整位置

  • jitter:随机抖一抖,让本来重叠的露出点头来

  • stack:叠罗汉

前面有讲到用法,此处就不再贴图了!代码如下:

g <- ggplot(d.sub,="" aes(x="cut," y="price," fill="">color))g + geom_bar(stat='summary', fun.y='mean', position='stack')g + geom_bar(stat='summary', fun.y='mean', position='fill')g + geom_bar(stat='summary', fun.y='mean', position='dodge')g + geom_bar(stat='summary', fun.y='mean', position='jitter')

对于抖动效果,加在散点图上比较有效果:

g <- ggplot(d.sub,="" aes(x="cut," y="price," fill="">color))g + geom_point(position='identity')g + geom_point(position='jitter')

  所以怎么调整还得看图形的需要。再看看x轴数据连续的图形:

g <- ggplot(d.sub,="" aes(x="price," fill="cut," color="">cut))g + stat_density(position='stack')g + stat_density(position='fill')g + stat_density(position='identity')g + stat_density(position='identity', fill='transparent')

4.6.3图层组合  

  图层的组合不是连续使用几个几何或统计类型函数那么简单。ggplot函数可以设置数据和映射,每个图层设置函数(geom_xxx和stat_xxx) 也都可以设置数据和映射,这虽然给组合图制作带来很大便利,但也可能产生一些混乱。如果不同图层设置的数据和映射不同,将会产生什么后果?得了解规则。

简单组合:

  不同的图层使用同一套数据,只是几何类型或统计类型有差别。这是最简单也是最常用的,用ggplot函数设置好数据和映射,把几个图层加起来即可:

datax <- data.frame(x="">1:10, y=rnorm(10)+1:10)g  <- ggplot(datax,="" aes(x="x," y="">y))g + geom_point() + geom_line()g + geom_point() + geom_smooth(method='lm')

  ggplot2的图层设置函数对映射的数据类型是有较严格要求的,比如geom_point和geom_line函数要求x映射的数据类型为数值向量,而 geom_bar函数要使用因子型数据。如果数据类型不符合映射要求就得做类型转换,在组合图形时还得注意图层的先后顺序:

datax <- data.frame(x="">1:10, y=rnorm(10)+1:10)g  <- ggplot(datax,="" aes(x="factor(x)," y="y))" +="">'x')g + geom_bar(stat='identity', fill='gray') +  geom_line(aes(group=1), size=2) +  geom_point(color='red')g + geom_bar(stat='identity', fill='gray') +  geom_smooth(aes(group=1), method='lm', se=FALSE, size=2)

  上面第一个图除了花哨一点外没有任何科学意义,如果放在论文中会被骂得狗学喷头:一套数据重复作图还都是一个意思,是不是脑子有病?但这里只是说明作图方 法。作图过程应先作柱形图,因为它要求x映射是因子型数据。x映射为因子的数据作散点图的调整步骤相对简单。如果先作散点图,把坐标轴从数值向量(连续 型)改为因子型相当麻烦。

不同映射的组合:

  映射反映的是数据变量。多数情况下一个图形中使用的是同一个数据集,只是变量不同。通常情况下x,y轴至少有一个是相同的,可以用不同图层叠加不同的数据变量:

g <- ggplot(d.sub,="" aes(x="carat))">   ylab('depth (blue) / table (red)')g + geom_point(aes(y=depth), color='blue')  +  geom_point(aes(y=table), color='red')

  但是为什么要这么做呢?预先处理一下数据再作图会更好,图标都已经帮你设好了:

library(reshape2)head(d.sub)##       carat       cut color clarity depth table price    x    y    z## 16601  1.01 Very Good     D     SI1  62.1    59  6630 6.37 6.41 3.97## 13899  0.90     Ideal     D     SI1  62.4    55  5656 6.15 6.19 3.85## 29792  0.30     Ideal     D     SI1  61.6    56   709 4.34 4.30 2.66## 3042   0.30 Very Good     G     VS1  62.0    60   565 4.27 4.31 2.66## 25272  2.06   Premium     I     SI2  61.0    61 13912 8.18 8.10 5.02## 26093  1.56 Very Good     G    VVS1  59.7    59 15334 7.48 7.57 4.49datax <- melt(d.sub,="" id.vars="">'carat', measure.vars=c('depth', 'table'))head(datax)##   carat variable value## 1  1.01    depth  62.1## 2  0.90    depth  62.4## 3  0.30    depth  61.6## 4  0.30    depth  62.0## 5  2.06    depth  61.0## 6  1.56    depth  59.7tail(datax)##      carat variable value## 995   0.91    table    56## 996   0.37    table    58## 997   1.27    table    58## 998   0.70    table    58## 999   0.71    table    62#3 1000  1.24    table    56ggplot(datax, aes(x=carat, y=value, color=variable)) + geom_point()

不同类型数据的组合:

  如果在geom_xxx函数中改变数据会怎么样呢?不同类型的数据一般不会有完全相同的变量,否则就不是“不同类型”了,所以映射也会相应做修改。下面把 钻石数据diamonds和汽车数据mtcars这两个风牛马不相及的数据放在一起看看。(首先声明:下面的方法只是演示,图形没有任何科学意义。科学图 形应该能让观众直观地了解数据,而不是让明白者糊涂让糊涂者脑残。有不少人喜欢用双坐标作混合数据图,个人认为那是很愚昧的做法。)

  diamonds数据我们在前面已经了解过了,先看看R datasets包里面的mtcars数据:

data(mtcars, package='datasets')str(mtcars)

## 'data.frame':    32 obs. of  11 variables:##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...##  $ disp: num  160 160 108 258 360 ...##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...##  $ qsec: num  16.5 17 18.6 19.4 17 ...##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

head(mtcars, 4)
##                 mpg cyl disp  hp drat    wt  qsec vs am gear carb## Mazda RX4      21.0   6  160 110 3.90 2.620 16.46  0  1    4    4## Mazda RX4 Wag  21.0   6  160 110 3.90 2.875 17.02  0  1    4    4## Datsun 710     22.8   4  108  93 3.85 2.320 18.61  1  1    4    1## Hornet 4 Drive 21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
g <- ggplot(data="d.sub," aes(x="carat," y="price," color="">cut))layer <- geom_point(aes(x="carb," y="mpg)," mtcars,="" color="">'black')(g <- g="" +="">

  图中数据点是正确的,但坐标轴标题却对不上号。看看ggplot对象的数据、映射和图层:

head(g$data, 4)##       carat       cut color clarity depth table price    x    y    z## 16601  1.01 Very Good     D     SI1  62.1    59  6630 6.37 6.41 3.97## 13899  0.90     Ideal     D     SI1  62.4    55  5656 6.15 6.19 3.85## 29792  0.30     Ideal     D     SI1  61.6    56   709 4.34 4.30 2.66## 3042   0.30 Very Good     G     VS1  62.0    60   565 4.27 4.31 2.66g$mapping## * x      -> carat## * y      -> price## * colour -> cutg$layers## [[1]]## mapping: x = carb, y = mpg ## geom_point: na.rm = FALSE## stat_identity: na.rm = FALSE## position_identity

  数据和映射都还是ggplot原来设置的样子,layer图层设置的都没有存储到ggplot图形列表对象的data和mapping元素中,而是放在了图层中,但图层中设定的数据不知道跑哪里。

  如果再增加一个图层,把坐标轴标题标清楚:

newlayer <- geom_point(aes(y="">depth))(g <- g="" +="" newlayer="" +="">'carb(black) / carat') + ylab('mpg(black) / depth'))

  newlayer重新指定了y映射,但没碰原来ggplot对象设置的x和color映射,从获得的图形来看y数据改变了,x和color还是原ggplot对象的设置。查看一下映射和图层:

g$mapping## * x      -> carat## * y      -> price## * colour -> cutg$layers## [[1]]## mapping: x = carb, y = mpg ## geom_point: na.rm = FALSE## stat_identity: na.rm = FALSE## position_identity ## ## [[2]]## mapping: y = depth ## geom_point: na.rm = FALSE## stat_identity: na.rm = FALSE## position_identity

  可以这么理解:ggplot2图层作图时依次从ggplot对象和图层中获取数据/映射,如果两者映射有重叠,后者将替换前者,但只是在该图层中进行替换而不影响ggplot对象。

  如果ggplot对象的映射比图层的映射多,而图层又使用了不同的数据,这是什么情况?看看:

g + geom_point(aes(x=carb, y=mpg), mtcars)## Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : ##                       参数值意味着不同的行数: 32, 0

  由于图层继承了ggplot对象的color映射,但又找不到数据,所以没法作图。解决办法是把原有的映射用NULL取代,或者设为常量(非映射):

g + geom_point(aes(x=carb, y=mpg, color=NULL), mtcars)g + geom_point(aes(x=carb, y=mpg), mtcars, color='red')

  photoshop流行的原因在于PS 3.0时引入图层的概念,ggplot的牛B之处在于使用+号来叠加图层,这堪称是泛型编程的典范。在前面散点图上,我们已经见识过,加上了一个回归线拟合的图层。有了图层的概念,使用ggplot画起图来,就更加得心应手。做为图层的一个很好的例子是蝙蝠侠logo,batman logo由6个函数组成,在下面的例子中,先画第一个函数,之后再加一个图层画第二个函数,不断重复这一过程,直到六个函数全部画好。

# batman logo是由六个函数构成的。# 利用ggplot2将多个线画到同一幅图案里面。 require(ggplot2)f1 <> function(x) {  y1 <->3*sqrt(1-(x/7)^2)  y2 <->3*sqrt(1-(x/7)^2)  y <> c(y1,y2)  d <- data.frame(x="">y)  d <- d[d$y=""> -3*sqrt(33)/7,]  return(d)}x1 <->3, 7, 0.001), seq(-7, -3, 0.001))d1 <> f1(x1)p1 <- ggplot(d1,aes(x,y))="" +="" geom_point(color="">'red')print(p1)

x2 <->4,4, 0.001)y2 <->2)-(3*sqrt(33)-7)*x2^2/112-3 + sqrt(1-(abs(abs(x2)-2)-1)^2)#only work with ggplot2 <=>0.8.9#p2 <- p1="" +="" geom_point(aes(x="x2,y=y2)," color="">'yellow')# in ggplot2 0.9.0, should be:d2 <- data.frame(x2="x2," y2="">y2)p2 <- p1="" +="" geom_point(data="d2," aes(x="x2,y=y2)," color="">'yellow')print(p2)

x3 <->0.75,1,0.001), seq(-1,-0.75,0.001))y3 <->9-8*abs(x3)#p3 <- p2+geom_point(aes(x="x3,y=y3)," color="">'green')d3 <- data.frame(x3="x3," y3="">y3)p3 <- p2+geom_point(data="d3," aes(x="x3,y=y3)," color="">'green')print(p3)

x4 <->0.5,0.75,0.001), seq(-0.75,-0.5,0.001))y4 <->3*abs(x4)+0.75#p4 <- p3+geom_point(aes(x="x4,y=y4)," color="">'steelblue')d4 <- data.frame(x4="">y4)p4 <- p3+geom_point(data="d4," aes(x="x4,y=y4)," color="">'steelblue')print(p4)

x5 <->0.5,0.5,0.001)y5 <->2.25,length(x5))#p5 <- p4+geom_point(aes(x="">y5))d5 <- data.frame(x5="">y5)p5 <- p4+geom_point(data="d5," aes(x="">y5))print(p5)

x6 <->3,-1,0.001), seq(1,3,0.001))y6 <->6 * sqrt(10)/7 +  (1.5 - 0.5 * abs(x6)) * sqrt(abs(abs(x6)-1)/(abs(x6)-1)) -  6 * sqrt(10) * sqrt(4-(abs(x6)-1)^2)/14#p6 <- p5+geom_point(aes(x="x6,y=y6)," colour="">'blue')d6 <- data.frame(x6="">y6)p6 <- p5+geom_point(data="d6,aes(x=x6,y=y6)," colour="">'blue')print(p6)

p <->theme_bw()print(p)

 



本公众号精彩历史文章

04:如何在R软件中求一致性指数( Harrell'concordance index:C-index)?

05:Nomogram 绘制原理及R&SAS实现.

06  : Lasso方法简要介绍及其在回归分析中的应用

07  : 最优模型选择中的交叉验证(Cross validation)方法

08  : 用R语言进行分位数回归(Quantile Regression)

09  : 样本数据中异常值(Outliers)检测方法及SPSS & R实现

10  : 原始数据中几类缺失值(Missing Data)的SPSS及R处理方法

11  :  [Survival analysis] Kaplan-Meier法之SPSS实现

12  :  [Survival analysis] COX比例风险回归模型在SPSS中的实现

13  :  用R绘制地图:以疾病流行趋势为例

14  :  数据挖掘方法:聚类分析简要介绍 及SPSS&R实现

15  :  医学研究中的Logistic回归分析及R实现

16  :  常用的非参数检验(Nonparametric Tests)总结

17  :  高中生都能看懂的最小二乘法原理

18  :  R语言中可实现的常用统计假设检验总结(侧重时间序列)

19  :  如何根据样本例数、均数、标准差进行T-Test和ANOVA

20  :  统计学中自由度的理解和应用

21  :  ROC和AUC介绍以及如何计算AUC

22  :  支持向量机SVM介绍及R实现

23  :  SPSS如何做主成分分析?

24  : Bootstrap再抽样方法简介

25  :  定量测量结果的一致性评价及 Bland-Altman 法的应用 

26  :  使用R绘制热图及网络图  

27  :  几种常用的双坐标轴图形绘制 

28  :  遗失的艺术—诺谟图(Nomogram) 

29  :  Nomogram 绘制原理及R&SAS实现(二) 

30  :  WOE:信用评分卡模型中的变量离散化方法 

31  :  结构方程模型(SEM)简介及教程下载  

32  :  重复测量的多因素方差分析SPSS实现操作过程 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多