ggplot2绘制Excel所有图

Posted by E-Phone Xu on June 13, 2016

目录

基于ggplot2-2.1.0,不定期补充更新,更多的资料请见 ggplot2官方文档

前言

此文献给熟练EXCEL图表制作的R入门使用者们。

1.用到的包

首先,需要加载做图中可能用到的一些工具包。

library(ggplot2) #作图包
library(dplyr) #数据转换包
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
library(tidyr) #数据转换包
library(splines) #数据差值包

2.数据准备

我们需要一些模拟数据,以作为后续作图的必备元素。

set.seed(123) #设定随机种子,保证做的图和这里的一样
df <- data.frame(
  var=LETTERS[1:10], #字母A-J
  id=1:10, #数字1-10
  a=runif(10), #10个随机数
  b=runif(10), #10个随机数
  c=runif(10), #10个随机数
  stringsAsFactors = F #不转换为因子
)
print(df) #显示数据
#>    var id         a          b         c
#> 1    A  1 0.2875775 0.95683335 0.8895393
#> 2    B  2 0.7883051 0.45333416 0.6928034
#> 3    C  3 0.4089769 0.67757064 0.6405068
#> 4    D  4 0.8830174 0.57263340 0.9942698
#> 5    E  5 0.9404673 0.10292468 0.6557058
#> 6    F  6 0.0455565 0.89982497 0.7085305
#> 7    G  7 0.5281055 0.24608773 0.5440660
#> 8    H  8 0.8924190 0.04205953 0.5941420
#> 9    I  9 0.5514350 0.32792072 0.2891597
#> 10   J 10 0.4566147 0.95450365 0.1471136

3.数据转换

上表是我们在excel中常见的数据集形式,但是在R中,由于作图需要,通常会转换为长数据的形式。

df1 <- df %>% gather("item",value,-1:-2) %>% 
  bind_cols(data.frame(item_id=rep(1:3,each=10))) #使用tidyr和dplyr包进行数据转换
print(df1) #显示数据
#>    var id item      value item_id
#> 1    A  1    a 0.28757752       1
#> 2    B  2    a 0.78830514       1
#> 3    C  3    a 0.40897692       1
#> 4    D  4    a 0.88301740       1
#> 5    E  5    a 0.94046728       1
#> 6    F  6    a 0.04555650       1
#> 7    G  7    a 0.52810549       1
#> 8    H  8    a 0.89241904       1
#> 9    I  9    a 0.55143501       1
#> 10   J 10    a 0.45661474       1
#> 11   A  1    b 0.95683335       2
#> 12   B  2    b 0.45333416       2
#> 13   C  3    b 0.67757064       2
#> 14   D  4    b 0.57263340       2
#> 15   E  5    b 0.10292468       2
#> 16   F  6    b 0.89982497       2
#> 17   G  7    b 0.24608773       2
#> 18   H  8    b 0.04205953       2
#> 19   I  9    b 0.32792072       2
#> 20   J 10    b 0.95450365       2
#> 21   A  1    c 0.88953932       3
#> 22   B  2    c 0.69280341       3
#> 23   C  3    c 0.64050681       3
#> 24   D  4    c 0.99426978       3
#> 25   E  5    c 0.65570580       3
#> 26   F  6    c 0.70853047       3
#> 27   G  7    c 0.54406602       3
#> 28   H  8    c 0.59414202       3
#> 29   I  9    c 0.28915974       3
#> 30   J 10    c 0.14711365       3

万事俱备后,接下来就可以作图了。 以下图形将严格按照excel 2016版中所有图形的出现顺序,读者可自行对照两者的异同。

柱形图

一般来说,ggplot的柱形图默认统计方法(stat)是计数(count)的,但是大多时候,我们更习惯于使用统计完成的数据,因此,在相关的图形参数中必须要增加stat=“identity”这一项。

1.簇状柱形图

簇状柱形图的特点是在不同类别中,不同变量的数据是横向排列的,因此需要图形参数中设置position="dodge"

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
  labs(title="aaa")

2.堆积柱形图

堆积柱形图的特点是在不同类别中,不同变量的数据是纵向堆积的,因此需要图形参数中设置position=“stack”

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="stack",width=0.8)+
  labs(title="aaa")

3.百分比堆积柱形图

百分比堆积柱形图的特点是在不同类别中,不同变量的数据转换为百分比后再纵向堆积,因此需要图形参数中设置position=“fill”

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="fill",width=0.8)+
  labs(title="aaa")

4.三维簇状柱形图

ggplot2中,所有作图均为平面图形,不推荐使用3D的呈现形式,因此此处不考虑作图。

5. 三维堆积柱形图

ggplot2中,所有作图均为平面图形,不推荐使用3D的呈现形式,因此此处不考虑作图。

6.三维百分比堆积柱形图

ggplot2中,所有作图均为平面图形,不推荐使用3D的呈现形式,因此此处不考虑作图。

7.三维柱形图——用分面替代

三维柱形图的特定是利用x轴和y轴分别表示两个分类变量,z轴表示具体数值,但是由于3D的遮挡性,所以通常可视化效果欠佳。在ggplot2中,可以用分面(facet_grid)解决这一问题。

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",width=0.8)+
  facet_grid(item~.)+
  labs(title="aaa")

折线图

在ggplot2中,自变量为分类变量的时候是不能使用折线图的,因此,需要将分类变量先转换/标记为数字(一开始df中设置id就是这个用处),然后在标签上使用scale_x_continuous()进行设置后就可以完美解决这一问题。

但是,依然不推荐使用分类变量刻画折线图!!!

1.折线图

折线图特点是每个变量先用散点标记,然后相连。因此全部使用默认参数即可。

ggplot(df1,aes(id,value,colour=item))+
  geom_line()+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10]) #改坐标轴

2.堆积折线图

堆积折线图特点是所有变量上的不同属性是纵向堆积关系,所以只要设置位置参数position="stack"即可。

ggplot(df1,aes(id,value,colour=item))+
  geom_line(position="stack")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

3.百分比堆积折线图

百分比堆积折线图特点是所有变量上的不同属性转换成百分比后再进行纵向堆积(所以最高那条线必定是直线…),所以只要设置位置参数position="fill"即可。

ggplot(df1,aes(id,value,colour=item))+
  geom_line(aes(ymax=0),position="fill")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

不过,这里需要注意的一点是,在aes()里必须设置ymax

4.带标记的折线图

带标记的折线图特点是在折线图基础上用了点标记,只要增加散点图就可以实现。

ggplot(df1,aes(id,value,colour=item))+
  geom_line()+
  geom_point()+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

5.带标记的堆积折线图

带标记的堆积折线图特点是在堆积折线图基础上用了点标记,只要增加散点图就可以实现。

ggplot(df1,aes(id,value,colour=item))+
  geom_line(position="stack")+
  geom_point(position="stack")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

6.带标记的百分比堆积折线图

带标记的百分比堆积折线图特点是在堆积折线图基础上用了点标记,只要增加散点图就可以实现。

ggplot(df1,aes(id,value,colour=item))+
  geom_line(aes(ymax=0),position="fill")+
  geom_point(aes(ymax=0),position="fill")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

7.三维折线图_用facet代替

三维折线图特点是利用x轴和y轴分别表示两个分类变量,z轴表示具体数值,但是由于3D的遮挡性,所以通常可视化效果欠佳。在ggplot2中,可以用分面(facet_grid)解决这一问题。

ggplot(df1,aes(id,value,colour=item))+
  facet_grid(item~.)+
  geom_line()+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

饼图

在ggplot2中,饼图和柱形图关系密切,其实就是一般的柱形图进行直角坐标轴到极坐标轴的转换即可。函数为coord_polar() 但是,同样的,大多人诟病饼图圆形面积不如柱形图的高低直观,因此并不推荐使用饼图。

1.饼图

饼图的特点是使用圆形的面积大小表示数据的占比份额。因此一般的饼图只要通过极坐标变换即可。

ggplot(df,aes(x = factor(1),a,fill=factor(var)))+
  geom_bar(stat="identity",position="fill")+
  coord_polar(theta="y")

需要注意的是,因为是对y轴进行转换,因此x轴长短需要一致,统一设置为某一值即可(本文使用x=factor(1))。 另外,需要注意的是,饼图通常是表示百分比,所以需要设置参数position="fill"

2.三维饼图

三维不做图。

3.复合饼图

复合饼图的特点是,当分类很多或者有一个分类含有子分类时,可以使用另一个图形将其中的内容显示出来。

df_tmp<-data.frame(x=1,y=1) #准备画布所需数据
base <- ggplot(df_tmp,aes(x,y))+
  geom_blank()+
  theme_void()+
  xlim(c(0,2))+
  ylim(c(0,2)) #准备画布
base + annotation_custom(
  grob = ggplotGrob(
    ggplot(df,aes(x = "",a,fill=factor(var)))+
    geom_bar(stat="identity",position="fill",
             show.legend = F)+
      labs(x=NULL,y=NULL)+
    coord_polar(theta="y")+
      theme_classic()),
  xmin =0,xmax=1,
  ymin=0.5,ymax = 1.5)+ # 图形1
  annotation_custom(
    grob = ggplotGrob(
      ggplot(df,aes(x = "",b,fill=factor(var)))+
                        geom_bar(stat="identity",
                                 position="fill",
                                 show.legend = F)+
                        labs(x=NULL,y=NULL)+
                        coord_polar(theta="y")+
                        theme_classic()),
    xmin =1.1,xmax=1.9,
    ymin=0.6,ymax = 1.4)+ #图形2
  annotate("segment",x=0.5,xend=1.5,
           y=0.69,yend=0.77)+ #线条1
  annotate("segment",x=0.5,xend=1.5,
           y=1.35,yend=1.28) #线条2

有心的读者应该可以看得出来,目前这一版本只是一个demo,仍然有很多需要改进的地方。 但是,实际上用这个图只是为了抛砖引玉,只要你有想象力和创造力,ggplot2可以很自由的帮你实现很多图表。

3.复合条饼图

复合条饼图的特点是,当分类很多或者有一个分类含有子分类时,可以使用另一个图形将其中的内容显示出来。

base <- ggplot(df_tmp,aes(x,y))+geom_blank()+theme_void()+
  xlim(c(0,2))+ylim(c(0,2))
base + annotation_custom(
  grob = ggplotGrob(
    ggplot(df,aes(x = "",a,fill=factor(var)))+
                      geom_bar(stat="identity",
                               position="fill",
                               show.legend = F)+
                      labs(x=NULL,y=NULL)+
                      coord_polar(theta="y")+theme_void()),
  xmin =0,xmax=1,
  ymin=0.5,ymax = 1.5)+
  annotation_custom(
    grob = ggplotGrob(
      ggplot(df,aes(x = "",b,fill=factor(var)))+
                        geom_bar(stat="identity",
                                 position="fill",
                                 show.legend = F)+
                        labs(x=NULL,y=NULL)+theme_void()),
    xmin =1.2,xmax=1.8,ymin=0.8,ymax = 1.2)+
  annotate("segment",x=0.5,xend=1.24,y=0.64,yend=0.84)+
  annotate("segment",x=0.5,xend=1.24,y=1.38,yend=1.18)+
  labs(title="aaa")

4.圆环图

圆环图的特点是每一个圆环表示一个变量,其中不同颜色表示不同的属性。

ggplot(df1,aes(x = item,value,fill=var))+
  geom_bar(stat="identity",position="fill",width=0.8,colour="white")+
  coord_polar(theta="y")

5.其他圆形图

这里不得不说一下,ggplot2的代码demo还是很赞的,用coord_polar可以创造出更多图形.

ggplot(df,aes(x = factor(1),a,fill=factor(var)))+
  geom_bar(stat="identity",position="dodge")+
  coord_polar(theta="y")


ggplot(df1,aes(x = id,value,fill=item))+
  geom_bar(stat="identity",position="fill",width=0.8)+
  coord_polar(theta="x")


ggplot(df,aes(x = var,a,fill=factor(var)))+
  geom_bar(stat="identity")+
  coord_polar(theta="x")

条形图

条形图就是横过来的柱形图,所以,只要一个coord_filp()即可。 需要注意的是,柱形图通常用于分类较少的情况下,分类较多且分类的名字特别长的时候,建议使用条形图。

1.簇状条形图

簇状条形图就是簇状柱形图转一下。

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
  labs(title="aaa")+
  coord_flip()

有心的小伙伴应该注意到了,excel做条形图的时候常常需要逆序坐标轴,但是这里没有做这个处理,就当做一个小小的BUG吧,交给读者自行处理。

2.堆积条形图

堆积条形图就是堆积柱形图转一下。

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="stack",width=0.8)+
  labs(title="aaa")+
  coord_flip()

3.百分比堆积条形图

百分比堆积条形图就是百分比堆积柱形图转一下。

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="fill",width=0.8)+
  labs(title="aaa",fill="")+
  coord_flip()

4.三维簇状条形图

3D就不做了

5.三维堆积条形图

3D就不做了

6.三维百分比条形图

3D就不做了

7.分面来代替3D

在柱形图里可以使用分面来代替3D柱形图,条形图一样可以

ggplot(df1,aes(var,value))+
  geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
  labs(title="aaa",fill="")+
  coord_flip()+
  facet_grid(.~item)

面积图

面积图就是一条折线图,然后用颜色把下面的区域全部覆盖了。通常情况下,当一条折线太单调的时候,使用面积图是不错的选择。

1.面积图

面积图的特点就是会覆盖所有该数据以下的区域。

ggplot(df1,aes(id,value))+
  geom_area(aes(fill=item),position=position_dodge(width = 0),
            alpha=0.5)+
  labs(title="aaa",fill="")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

这里需要注意的是,位置函数需要特别定义position=position_dodge(width = 0)。 另外,多分类的时候,应当设置透明度,如alpha=0.5

2.堆积面积图

堆积面积图特点是会一层一层覆盖上去

ggplot(df1,aes(id,value))+
  geom_area(aes(fill=item),alpha=0.5)+
  labs(title="aaa")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

3.百分比堆积面积图

百分比堆积面积图特点是先把数据转换为百分比,然后一层一层覆盖上去

ggplot(df1,aes(id,value))+
  geom_area(aes(fill=item),position="fill",alpha=0.5)+
  labs(title="aaa",fill="")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

4.三维面积图

3D不做图

5.三维堆积面积图

3D不做图

6.三维百分比堆积面积图

3D不做图

7.分面来代替3D

如果觉得面积图用透明度也一样不是很清楚的话,那不妨用分面。

ggplot(df1,aes(id,value))+
  geom_area(aes(fill=item),position="stack",alpha=0.5)+
  labs(title="aaa",fill="")+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
  facet_grid(item~.)

XY散点图

怎么说呢,散点图基本上来说是所有图形的基础图形,所以一直以来对散点图还是有很深的感情。 说到散点图本身,其实就是知道x和y坐标,然后把点放上去的一种图形。

1.散点图

散点图的特点是,已知x和y的数值,然后把点放上去。

ggplot(df1,aes(var,value))+
  geom_point(aes(colour=item))

2.带平滑线和数据标记的散点图

带平滑线和数据标记的散点图的特点是,已知x和y的数值,然后把点放上去。然后用平滑的曲线连起来。

df1_a<-df1 %>% filter(item=="a") %>% select(value) %>% 
  unlist %>% spline(,1000) %>% as.data.frame()
df1_b<-df1 %>% filter(item=="b") %>% select(value) %>% 
  unlist %>% spline(,1000) %>% as.data.frame()
df1_c<-df1 %>% filter(item=="c") %>% select(value) %>% 
  unlist %>% spline(,1000) %>% as.data.frame()

df1_sp<-bind_rows(df1_a,df1_b,df1_c) %>% 
  mutate(item=rep(letters[1:3],each=1000))

ggplot()+
  geom_point(data=df1,aes(id,value,colour=item))+
  geom_line(data=df1_sp,aes(x,y,colour=item))+
  scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])