分享

ggplot2

 无名小卒1990 2015-01-24

从ggplot2的qplot()开始,qplot()的用法与plot()有一定的相似之处,所以如果熟悉plot(),那么学习起来qplot()也不会太难。

数据集使用diamonds,首先用summary()查看一下数据集的基本特性吧!


数据说明:


然后创建一个含有100条记录的diamonds的子集dsmall:

  1. set.seeds(1410) 
  2. dsmall<-diamonds[sample(nrow(diamonds),100),] 
  1. set.seeds(1410)  
  2. dsmall<-diamonds[sample(nrow(diamonds),100),]  
set.seeds()应该是给下面的随机取样过程设定的某个条件,具体原理我也不是很清楚,还请多多指教。

sample()用来在所有的diamonds记录中随机抽取100个作为dsmall

最为基本的用法:

qplot()的前两个参数分别是x与y,给出坐标点的横纵坐标,data参数可选。

  1. qplot(carat,price,data=diamonds) 
  1. qplot(carat,price,data=diamonds)  


除了一些显著的outlier以外,x与y有显著的相关性,同时在y轴方向上可以观察到有显著的断面。从图像上看,x与y成指数关系,所以我们可以对两组值进行适当的转换后再重新作图使得趋势更为明显。qplot()的参数可以为函数,所以分别对x值与y值取对数:

  1. qplot(log(carat),log(price),data=diamonds) 
  1. qplot(log(carat),log(price),data=diamonds)  


看吧,显著的线性关系来了是不是呢!当然了,qplot()还可以接受不同变量的组合作为参数,如果我们想研究钻石的体积与重量之间的关系(体积约等于x*y*z),那么:

  1. qplot(carat,x*y*z,data=diamonds) 
  1. qplot(carat,x*y*z,data=diamonds)  


从上图中我们基本可以推断出钻石的密度是一个基本恒定值,因为体积与质量的比值是大体不变的。

对坐标点颜色,大小,形状以及其他外观参数的设定

在使用qplot()与plot()时最大的不同之一就是对于点的颜色,大小,形状等性质的设定。如果使用plot()函数,你需要自己去将类型变量转换成plot()函数可以识别的控制外观的参数,但是在qplot()中,这一过程可以自动完成:

  1. qplot(carat,price,data=dsmall,color=color 
  1. qplot(carat,price,data=dsmall,color=color  


  1. qplot(carat,price,data=dsmall,shape=cut) 
  1. qplot(carat,price,data=dsmall,shape=cut)  

对于每一个外观参数,都有一个scale函数将数据与有效地参数逐一对应起来,例如在对坐标点颜色进行改变的例子中,函数将J对应为紫色,而将F对应为绿色。

对于像diamonds这样较大的数据及而言,设置点的透明度可以有效地减少坐标点重合的问题。alpha参数可以设置为0(完全透明)到1(完全不透明)中的任意值。很多时候,alpha的值可以用分数来表示。

  1. qplot(carat,price,data=diamonds,alpha=I(1/10)) 
  2. qplot(carat,price,data=diamonds,alpha=I(1/100)) 
  3. qplot(carat,price,data=diamonds,alpha=I(1/200)) 
  1. qplot(carat,price,data=diamonds,alpha=I(1/10))  
  2. qplot(carat,price,data=diamonds,alpha=I(1/100))  
  3. qplot(carat,price,data=diamonds,alpha=I(1/200))  


不同的外观参数适用于不同的数据类型。对于分类数据的区分最好用颜色与形状参数,而连续数据最好用大小表示,同时,数据集的大小也是一项重要的考虑因素。

为图像添加平滑线

如果仅仅有数据的散点图,你可能很难看出数据的总体趋势。在这种情况下,给图像添加平滑线是很好的选择。在geom中添加"smooth"便可以轻松的完成这项任务。给geom参数设置一列向量可以组合多个几何图形元素。

  1. qplot(carat, price, data = diamonds, geom = c("point", "smooth")) 
  1. qplot(carat, price, data = diamonds, geom = c("point", "smooth"))  


平滑的算法也有很多可供选择:

method=“loess“:对于较小数据集的默认平滑算法,平滑程度由span参数来进行设定。span=0时线较为弯曲,span=1时最为平缓。

  1. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),span = 0.2) 
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),span = 1) 
  1. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),span = 0.2)  
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),span = 1)  



由于算法复杂度的原因,对于大的数据集loess并不是十分适用。

method="gam":当数据点大于1000时,这是默认的平滑算法。

  1. library(mgcv) 
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "gam", formula = y ~ s(x)) 
  1. library(mgcv)  
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "gam", formula = y ~ s(x))  



method="lm":用于线性模型。默认为一条直线,也可以用formula=y~poly(x,2)设置为二次函数拟合,或者加载splines包用formula=y~ns(x,2),第二个参数表示自由度,自由度越高拟合曲线也就越弯曲。

  1. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "lm") 
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "lm", formula = y ~ ns(x,5)) 
  1. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "lm")  
  2. qplot(carat, price, data = dsmall, geom = c("point", "smooth"),method = "lm", formula = y ~ ns(x,5))  

绘制箱线图和抖动图:

当一组数据既有分类变量又有连续变量的时候,你可能会对连续变量在不同分类下的变化感兴趣,箱线图和抖动图是实现这一目的的两种不同方法。

  1. qplot(color, price / carat, data = diamonds, geom = "jitter",alpha = I(1 / 200)) 
  1. qplot(color, price / carat, data = diamonds, geom = "jitter",alpha = I(1 / 200))  



  1. qplot(color, price / carat, data = diamonds, geom = "boxplot") 
  1. qplot(color, price / carat, data = diamonds, geom = "boxplot")  



直方图和密度图:

直方图和密度图可以形象的显示单一变量的分布规律,但是难以比较不同类之间分布的区别。

  1. qplot(carat, data = diamonds, geom = "histogram") 
  2. qplot(carat, data = diamonds, geom = "density") 
  1. qplot(carat, data = diamonds, geom = "histogram")  
  2. qplot(carat, data = diamonds, geom = "density")  




对于不同分类间的比较,可以像下面代码所示加一个外观参数选项:

  1. qplot(carat, data = diamonds, geom = "density", colour = color) 
  2. qplot(carat, data = diamonds, geom = "histogram", fill = color) 
  1. qplot(carat, data = diamonds, geom = "density", colour = color)  
  2. qplot(carat, data = diamonds, geom = "histogram", fill = color)  




柱状图:

离散变量的直方图即柱状图,用geom="bar"来设置。

  1. qplot(color, data = diamonds, geom = "bar") 
  2. qplot(color, data = diamonds, geom = "bar", weight = carat) +scale_y_continuous("carat") 
  1. qplot(color, data = diamonds, geom = "bar")  
  2. qplot(color, data = diamonds, geom = "bar", weight = carat) +scale_y_continuous("carat")  




时间序列分析:

用含有时间数据的economics数据集,做失业率随时间变化的图像:

  1. qplot(date, unemploy / pop, data = economics, geom = "line") 
  1. qplot(date, unemploy / pop, data = economics, geom = "line")  



观察失业率与周失业人数中位数之间的关系:

  1. year <- function(x) as.POSIXlt(x)$year + 1900 
  2. qplot(unemploy / pop, uempmed, data = economics,geom = "path", colour = year(date)) + scale_area() 
  1. year <- function(x) as.POSIXlt(x)$year + 1900  
  2. qplot(unemploy / pop, uempmed, data = economics,geom = "path", colour = year(date)) + scale_area()  



分面:

我们已经讨论了如何利用外观参数在同一图中比较不同分类的差异。而分面可以将不同的亚类放在不同的图中进行比较:

  1. qplot(carat, data = diamonds, facets = color ~ .,geom = "histogram", binwidth = 0.1, xlim = c(0, 3)) 
  1. qplot(carat, data = diamonds, facets = color ~ .,geom = "histogram", binwidth = 0.1, xlim = c(0, 3))  



关于ggplot2的语法基础- 图层

首先绘制一张最简单的统计图:



qplot(displ, hwy, data = mpg, colour = factor(cyl))



量化:

在R中绘图时,我们往往用下表的格式来存储数据:


但是,这种格式对于计算机来说是毫无意义的。我们需要将数据单元(如,单位耗油量、气缸数)转化成计算机可以显示的物理单元(如,像素,颜色)。这个过程就被称作量化。但是,对于计算机而言有意义的数据我们又不一定能理解:颜色用四位十六进制数来表示,数字代表大小,整数代表一种形状。

在这一例中,我们有三个需要被量化的外观参数:水平位置(x),垂直位置(y)以及颜色。在这一例子中,对于位置的量化比较简单,因为我们用的是默认的线性量表。我们只需要将数据线性映射到0到1的范围内即可。这里我们用0到1的范围而不是实际的像素值,因为ggplot2应用的grid绘图体系会自动完成后续的转化。最后要将x与y结合从而定位数据点,这一步由坐标系统(coord)完成。大多数情况下会采用笛卡尔坐标系,但有时也会用到极坐标系,绘制地图时会用到球形投影。

颜色的添加过程更加复杂一些,因为结果是非数值型的。然而,与人眼对于颜色的识别机制类似,计算机对颜色的编码也由三部分构成,这三部分构成一个三维的颜色空间。量化颜色也就转化为了找到特定颜色在该空间所对应的点。实现这一过程的方法有很多种,但是由于cyl是一个离散变量,我们可以在颜色空间上均匀的找到点来表示这些颜色,结果如下图所示。对于连续变量的转化与此并不相同。


上表所示的数据是计算机可以识别的。我们也将转化过的外观参数添加了上去。这样每一个点都已经被很好地定义过,R就可以将他们一一画下来了。

最后,我们就可以用这些元素画出想要的图形了。一个完整的图形往往包含以下几部分:点所代表的数据,量表以及坐标系和附注。量表和坐标系绘制坐标轴以及图例,这样我们就可以从图中读出参数。附注添加图的名称和一些背景信息。

更复杂的图形:

了解了简单模型以后,下面我们看看稍微复杂一点的情况吧。下面的图形在一开始的基础上添加了新的元素:分面,多个图层以及统计数据。分面和图层扩展了上面提到的数据结构:每一个分面的每一个图层都有属于自己的数据集。你可以将它想象成是一个三维的数组:分面构成了二维平面,然后图层给予其在新的维度上的扩展。在这个例子中,不同图层上的数据是一样的,但是从理论上来讲,不同的图层中可以有不同的数据。

qplot(displ, hwy, data=mpg, facets = . ~ year) + geom_smooth()


下表是每个分面上的几行数据:


平滑图层与散点图图层的不同之处在于它不显示原始的数据,而是给出了统计方法处理过后的结果。而且,平滑图层会给出拟合的平滑曲线,这要求额外的步骤:在被转化成其对应的外观参数之后,数据将会由stat进行统计转化,对其进行一些非常有用的处理。在本例中,stat对数据进行loess平滑处理,并返回在自变量范围内的预测值。(其他有用的统计转化:1 and 2d binning, group means, quantile regression and contouring)

除了需要更多的步骤对数据进行处理,我们也需要一些额外的步骤对量表进行处理。因为我们现在有多个数据集(不同的分面,不同的图层),我们需要保证个数据集间的量表保持一致。量化的过程分为三步:转换,训练和对应。我们之前没有提到过转换,但是在做log-log图时有用到过。在log-log图中,数据与坐标并不是线性对应的,而是要先经过对数转换。

量化在统计之前,因此stat是对量化后的数据进行的处理。这样可以保证在线性坐标系中log(x) vs. log(y)与对数坐标系中x vs. y的一致性。还有很多其他的转换可供选择:如平方根转换,对数转换和倒数转换。

统计过后,量表会在所有的图层和分面上进行调整。调整过程结合所有数据集以获得最终的取值范围。没有这一步,量表只对局部的数据有意义,而且由于无法对应,我们不能叠加不同的图层。有时,不同分面之间的量表可能不需要调整(但不同图层间必须调整)。

最后,量表与数据一一对应。这是一个局部过程:他们形成一个新的数据集。

流程示意图:





层式语法的构成:

在上面的例子中,我们了解了构成图像的基本元素:数据,外观参数,几何对象,统计转换,量表以及分面。我们也探讨了一些关于坐标系的内容。而未涉及到位置调整,这其实与处理重叠对象密不可分。上述元素结合在一起形成图层。一个图像可能会有很多图层,就像一开始我们将平滑线加到散点图上一样。层式语法将图层定义为以下几种元素的组合:

·数据集以及数据与外观参数的对应

·一到多个图层,每个图层都包含几何元素,统计转换,位置调整,并可能有数据集及其对应的外观参数

·统一的量表

·坐标系统

·分面


简介:

ggplot2的层式结构使得系统的绘图成为可能。你现在已经知道了什么是图层和如何将图层添加到自己所绘制的图像上,但是什么类型的图形才能最合理的对数据进行展示呢?这一部分将根据不同的功能将图形进行分类介绍。

在添加新的图层之前,最好先想一想你想用这一图层达到什么目的。下面是图层最为常见的几种作用:

·数据的展示。

原始数据的绘制很重要,我们要手工对整体以及局部的数据结构和异常值进行判断。在数据处理的早期阶段,数据图层往往就是唯一的图层。

·统计结论的展示。

在我们对数据模型进行研究的时候,在原始数据上同时添加模型预测结果也是很好的选择。我们可以根据统计检验来评估模型的好坏。将原始数据与模型放在一起,既有利于我们查看模型的好坏,又有利于我们对原始数据更加深入的观察。

·宏数据、背景以及注释的添加。

宏数据层可以添加背景信息以及注释,从而让我们更好地理解原始数据。宏数据层既可以放在底层又可以放在顶层。在在绘制地理数据时,地图往往被放在底层。放在底层的宏数据有最小的可视性,因此不会干扰你对原始数据的观察。这就意味着,如果你关心宏数据,你可以容易地观察到它,但如果你只想认真检视数据,宏数据又一点也不会干扰到你。

还有一些宏数据是为了强调重要的信息。你有时可能要对一些重要的拐点和异常值添加注释信息,那你就希望这些东西可以夺人眼球,这种情况下,宏数据最好放在最后添加。

基本绘图类型:

这些几何元素是ggplot的基础。他们彼此结合可以构成复杂的图像。他们中的绝大多数对应特定的绘图类型。

geom_area()

geom_bar()

geom_line()

geom_point()

geom_polygon()

geom_text()

geom_tile()

下面是例子哟:

df <- data.frame(x = c(3, 1, 5),y = c(2, 4, 6),label = c("a","b","c"))

p <- ggplot(df, aes(x, y, label = label)) +xlab(NULL) + ylab(NULL)
p + geom_point() + opts(title = "geom_point")
p + geom_bar(stat="identity") +opts(title = "geom_bar(stat=\"identity\")")

#stat="identity"一定要有的,不然R会自己数个数去的

p + geom_line() + opts(title = "geom_line")
p + geom_area() + opts(title = "geom_area")
p + geom_path() + opts(title = "geom_path")
p + geom_text() + opts(title = "geom_text")
p + geom_tile() + opts(title = "geom_tile")
p + geom_polygon() + opts(title = "geom_polygon")



 


数据分布的的表示:

显示数据分布规律的方法有很多,这取决于数据的维数,离散还是连续数据,你是对条件分布感兴趣还是对联合分布感兴趣。

对于一维的连续数据最重要的分布图就是直方图。下图是diamond depth的分布直方图。bin的参数对于直方图的外观相当重要,可以用binwidth或break参数进行设置。

depth_dist <- ggplot(diamonds, aes(depth)) + xlim(58, 68)
depth_dist +geom_histogram(aes(y = ..density..), binwidth = 0.1) +facet_grid(cut ~ .)
depth_dist + geom_histogram(aes(fill = cut), binwidth = 0.1,position = "fill")
depth_dist + geom_freqpoly(aes(y = ..density.., colour = cut),binwidth = 0.1)


大数据的处理:

散点图对于估计两个连续变量之间的关系非常有用。但是如果数据量很大的时候,点与点之间就会相互重叠,从而掩盖两变量之间真实的关系。有些情况下,你可能只能在图中看出数据大体的分布范围,因此任何的结论都是值得怀疑的。这一问题被称为“overplotting”,解决方法主要有以下几种:

·对于少数点的overplotting,可以将点画的小一些,或者改变点的形状。如下图所示:

df <- data.frame(x = rnorm(2000), y = rnorm(2000))
norm <- ggplot(df, aes(x, y))
norm + geom_point()
norm + geom_point(shape = 1)
norm + geom_point(shape = ".")


·对于更大的数据集,可以用alpha参数设置数据点的透明度。在R中,透明度的最小值可以设到1/256,所以对于特别大的数据集也是无能为力。

norm + geom_point(colour = 'black', alpha=1/3)
norm + geom_point(colour = 'black', alpha=1/5)
norm + geom_point(colour = 'black', alpha=1/10)


·如果数据本身具有一定的离散性,那么可以随机抖动数据点以减少重叠。跟透明度设置联合应用效果最好。

td <- ggplot(diamonds, aes(table, depth)) +xlim(50, 70) + ylim(50, 70)
td + geom_point()
td + geom_jitter()
jit <- position_jitter(width = 0.5)
td + geom_jitter(position = jit)
td + geom_jitter(position = jit,  alpha= 1/10)
td + geom_jitter(position = jit, alpha=1/50)
td + geom_jitter(position = jit,  alpha=1/200)


·将数据分组并统计每组内数据的个数,然后将个数展示出来(二维直方图形式)。把图形分成许多的小块可以呈现出特殊的视觉效果。六边形也是可以的,bins和binwidth参数控制小格的数目和大小。(需要hexbin包)

d <- ggplot(diamonds, aes(carat, price)) + xlim(1,3) +opts(legend.position = "none")
d + stat_bin2d()
d + stat_bin2d(bins = 10)
d + stat_bin2d(binwidth=c(0.02, 200))
d + stat_binhex()
d + stat_binhex(bins = 10)
d + stat_binhex(binwidth=c(0.02, 200))



 

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多