ggplot2绘制常见基本图形

Posted by Bruce Zhao on May 31, 2016

Estimated reading time: 19 minutes. {R} [ggplot2]

目录

{: .no_toc}

本篇文章基于ggplot2-2.1.0,有数据格式 + 代码,方便套用。 不定期更新中,更多的资料请见ggplot2官方文档

背景图片代码:

ggplot(diamonds, aes(carat, price,colour=cut)) +
    geom_point(alpha = 1/3) +
    stat_smooth() + xlim(0,4) +
    theme(text=element_blank(),
        line=element_blank(),
        legend.position="none",
        title=element_blank())
ggsave("ggplot-basic.jpg",width = 8,height = 4.5,dpi=600)

占比饼图

有没有发现ggplot2里面没有直接画饼图的函数,这需要做一些小改变:将柱状图的笛卡尔坐标系变为极坐标。下面来简单介绍一下画法。

数据要求:

print(xueli_zb_plot)
#> Source: local data frame [5 x 3]
#> 
#>       xueli1 ratio mid_y
#>       <fctr> <dbl> <dbl>
#> 1 博士研究生  0.06 0.030
#> 2 硕士研究生  0.24 0.180
#> 3   大学本科  0.53 0.565
#> 4   大学专科  0.15 0.905
#> 5 高中及以下  0.03 0.995

画图代码:

library(ggplot2)
#定义画图字体
windowsFonts(myfont=windowsFont("等线"))

ggplot(xueli_zb_plot, aes(x = ‘’, y = ratio,fill=xueli1,label=ratio)) + geom_bar(width = 1,stat="identity") + geom_text(aes(y = mid_y)) + coord_polar(theta = "y") + labs(y="比例",title="学历占比") + theme_bw() + guides(fill=guide_legend(title = "学历")) + theme(axis.text.y= element_blank(), axis.ticks = element_blank(), axis.text.x= element_blank(), axis.title.y= element_blank(), text=element_text(family = "myfont"), title=element_text(family = "myfont",face="bold"))

占比饼图

堆积柱状图

用于比较各变量的构成比

数据要求:

print(zy)
#>   志愿类型 人数 比例    学校 mid_y
#> 1 第二志愿  460 0.22 school1  0.11
#> 2 第一志愿 1655 0.78 school1  0.61
#> 3 第二志愿 3217 0.46 school2  0.23
#> 4 第一志愿 3709 0.54 school2  0.73

画图代码:

ggplot(zy, aes(学校, fill = 志愿类型,y = 比例,label = 比例)) + 
  geom_bar(position = "stack",stat="identity",width = 0.8) +
  labs(title ="一二志愿比例柱状图", y = "比例") +
  geom_text(aes(y = mid_y)) +
  theme_bw() +
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

堆积柱状图

直方图

用于探索数据分布情况

一般直方图

数据要求:

head(plot_hist)
#> Source: local data frame [6 x 1]
#> 
#>   客观总分
#>      <dbl>
#> 1     38.0
#> 2     34.5
#> 3     34.5
#> 4     33.5
#> 5     33.5
#> 6     33.5

画图代码:

ggplot(plot_hist,aes(客观总分)) + 
  geom_histogram(binwidth = 2,colour="black",fill="white") +
  labs(title="客观总分人数分布直方图",y='人数',x="客观总分")+
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

一般直方图

分面直方图

数据要求:

print(plot_hist_facet %>% sample_n(6))
#> Source: local data frame [6 x 2]
#> 
#>           vd value
#>        <chr> <dbl>
#> 1       记忆   1.0
#> 2       表达  12.5
#> 3   注意理解   7.0
#> 4 社会性情绪   8.5
#> 5       表达   9.5
#> 6       表达  11.0

画图代码:

ggplot(plot_hist_facet,aes(value,group=vd))+
  geom_histogram(binwidth = 2,colour="black",fill="white") +
  facet_grid(.~vd)+
  labs(title="各项得分人数分布直方图",y='人数',x="各项得分")+
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

分面直方图

密度图

探索变量的分布情况

数据要求:

print(zf_zy)
#> Source: local data frame [2,112 x 2]
#> 
#>    user_zhiyuan final
#>          <fctr> <dbl>
#> 1      第一志愿  38.0
#> 2      第一志愿  34.5
#> 3      第一志愿  34.5
#> 4      第一志愿  33.5
#> 5      第一志愿  33.5
#> 6      第二志愿  33.5
#> 7      第一志愿  32.5
#> 8      第一志愿  32.5
#> 9      第二志愿  32.0
#> 10     第一志愿  31.5
#> ..          ...   ...
cdat <- zf_zy %>% group_by(user_zhiyuan) %>% summarise(mean=mean(final))
print(cdat)
#> Source: local data frame [2 x 2]
#> 
#>   user_zhiyuan     mean
#>         <fctr>    <dbl>
#> 1     第一志愿 18.65296
#> 2     第二志愿 19.03384

画图代码:

ggplot(zf_zy,aes(x=final,colour=user_zhiyuan,fill=user_zhiyuan)) +
  geom_density(alpha=0.3,show.legend = T,adjust=1.5) +
  labs(title="一二志愿总分密度图",
       x="总分",
       colour="志愿类型",
       fill="志愿类型") +
  theme_bw()+
  geom_vline(data=cdat,aes(xintercept=mean,colour=user_zhiyuan),linetype="dashed",size=1)+
  theme(text=element_text(family = "myfont"),
        legend.position=c(1,1),legend.justification=c(1,1),
        title=element_text(family = "myfont",face="bold"))

密度图

箱线图

用于探索&比较各变量的分布情况

正常箱线图

数据要求:

print(boxplot_time)
#> Source: local data frame [2,046 x 2]
#> 
#>    时间段 客观总分
#>     <chr>    <dbl>
#> 1   08:00     17.5
#> 2   08:00     23.0
#> 3   08:00     20.5
#> 4   08:00     20.0
#> 5   08:00     25.5
#> 6   08:00     23.5
#> 7   08:00     18.0
#> 8   08:00     23.0
#> 9   08:00     21.5
#> 10  08:00     22.0
#> ..    ...      ...

画图代码:

ggplot(boxplot_time,aes(时间段,客观总分,colour=时间段)) + 
  #标出离群点
  geom_boxplot(colour="darkgrey",outlier.colour = "red", outlier.shape = 2,outlier.size = 3) + 
  geom_jitter(width = 0.1,size=0.8) +
  ggtitle("各个时段得分箱线图")+
  theme_bw() +
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

正常箱线图

旋转90°箱线图

数据要求:

print(boxplot_xueli)
#> Source: local data frame [2,112 x 2]
#> 
#>        xueli1 stu_final
#>        <fctr>     <dbl>
#> 1    大学本科      38.0
#> 2    大学专科      34.5
#> 3    大学本科      34.5
#> 4    大学本科      33.5
#> 5    大学本科      33.5
#> 6  博士研究生      33.5
#> 7  博士研究生      32.5
#> 8    大学专科      32.5
#> 9    大学本科      32.0
#> 10   大学本科      31.5
#> ..        ...       ...

画图代码:

ggplot(boxplot_xueli,aes(x=xueli1,y=stu_final,colour=xueli1))+
  geom_boxplot(colour="darkgrey",outlier.colour = "red", outlier.shape = 2,outlier.size = 3) +    #标出离群点
  geom_jitter(width = 0.1,size=1.5,show.legend = T) +
  guides(col = guide_legend(reverse = TRUE,title = "学历"))+ #翻转图例
  coord_flip() +
  theme_bw() +
  labs(y="得分",title="学历与得分箱线图") + #图例标题
  theme(text=element_text(family = "myfont"),
        axis.title.y= element_blank(),
        title=element_text(family = "myfont",face="bold"))

旋转90°箱线图

分面图

用于展示各个维度的情况。

分面条形图

用于比较各变量平均水平。

数据要求:

print(huji_fmt)
#> Source: local data frame [21 x 3]
#> Groups: user_type1 [?]
#> 
#>    user_type1      vd    平均分
#>        <fctr>   <chr>     <dbl>
#> 1    人户一致 att_com  6.687500
#> 2    人户一致     cod  1.404261
#> 3    人户一致     exp 12.289583
#> 4    人户一致     log  4.569034
#> 5    人户一致     mem  2.771023
#> 6    人户一致     soc 12.465814
#> 7    人户一致     spa  3.463636
#> 8    人户分离 att_com  6.744966
#> 9    人户分离     cod  1.322148
#> 10   人户分离     exp 12.143177
#> ..        ...     ...       ...

画图代码:

ggplot(huji_fmt,aes(user_type1,平均分,group=vd,fill=vd))+
  geom_bar(stat="identity") +
  labs(title="不同户籍下平均分柱状图",
       x="\n学生户籍",
       fill="维度") +
  theme_bw() +
  facet_grid(.~vd) +
  theme(text=element_text(family = "myfont"),
        axis.text.x=element_text(angle = 315,vjust = 0.5,hjust = 0.5),
        title=element_text(family = "myfont",face="bold"))

分面条形图

分面散点+拟合线

用于反映各变量的变化趋势。

数据要求:

print(fmt)
#> Source: local data frame [2,163 x 3]
#> Groups: hm [309]
#> 
#>                     hm     vd   平均分
#>                 <time> <fctr>    <dbl>
#> 1  2016-05-07 08:09:00   表达 13.00000
#> 2  2016-05-07 08:10:00   表达 11.07143
#> 3  2016-05-07 08:11:00   表达 12.28571
#> 4  2016-05-07 08:12:00   表达 11.25000
#> 5  2016-05-07 08:13:00   表达 10.88462
#> 6  2016-05-07 08:15:00   表达 12.17647
#> 7  2016-05-07 08:16:00   表达 14.00000
#> 8  2016-05-07 08:18:00   表达 12.75000
#> 9  2016-05-07 08:19:00   表达 12.69231
#> 10 2016-05-07 08:20:00   表达 10.50000
#> ..                 ...    ...      ...

画图代码:

ggplot(fmt,aes(hm,平均分,colour=vd))+
  geom_point(size=0.8)+
  stat_smooth(size=0.8)+
  labs(title="各个时段各维度平均分图",
       x="时间段",colour="各维度") +
  facet_grid(vd~.) +
  theme_bw() +
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

分面散点+拟合线

分面折线图

数据要求:

print(xueli_fmt)
#> Source: local data frame [35 x 3]
#> Groups: xueli1 [?]
#> 
#>        xueli1      vd    平均分
#>        <fctr>   <chr>     <dbl>
#> 1  博士研究生 att_com  7.024000
#> 2  博士研究生     cod  1.328000
#> 3  博士研究生     exp 11.969333
#> 4  博士研究生     log  4.452000
#> 5  博士研究生     mem  2.656000
#> 6  博士研究生     soc 11.850667
#> 7  博士研究生     spa  3.552000
#> 8  硕士研究生 att_com  6.692771
#> 9  硕士研究生     cod  1.370482
#> 10 硕士研究生     exp 12.366466
#> ..        ...     ...       ...

画图代码:

ggplot(xueli_fmt,aes(xueli1,平均分,colour = vd,group=vd))+
  geom_line(size=1)+
  labs(title="不同学历各维度平均分折线图",
       x="\n学历") +
  theme_bw() +
  guides(col = guide_legend(title = "各维度"))+ 
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

分面折线图

滑珠图

数据要求:

print(hzt)
#> Source: local data frame [14 x 3]
#> Groups: 性别 [2]
#> 
#>      性别         vd    平均分
#>    <fctr>     <fctr>     <dbl>
#> 1      女       表达 12.653226
#> 2      男       表达 12.011254
#> 3      女       记忆  2.738780
#> 4      男       记忆  2.771268
#> 5      女   逻辑推理  4.341197
#> 6      男   逻辑推理  4.610353
#> 7      女 社会性情绪 12.760177
#> 8      男 社会性情绪 12.210879
#> 9      女 视空间加工  3.247411
#> 10     男 视空间加工  3.542536
#> 11     女       书动  1.481567
#> 12     男       书动  1.311897
#> 13     女   注意理解  6.782509
#> 14     男   注意理解  6.596308

画图代码:

ggplot(hzt,aes(x=vd,y=平均分)) +
  geom_linerange(aes(ymin=0,ymax=平均分),color='gray',size=1) +
  geom_point(aes(colour=性别),size=5) +
  ggtitle("男女生各维度平均值滑珠图") +
  ylim(0,15) +
  theme_bw() +
  coord_flip() +
  theme(axis.title.y=element_blank(),
        text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold")) 

滑珠图

二维密度图

数据要求:

print(plot_2d)
#> Source: local data frame [2,112 x 2]
#> 
#>       v1    v2
#>    <dbl> <dbl>
#> 1   26.0  24.0
#> 2   28.5  22.5
#> 3   26.5  22.5
#> 4   23.0  24.5
#> 5   23.0  20.5
#> 6   19.0  22.5
#> 7   22.0  21.5
#> 8   25.5  20.5
#> 9   20.5  22.0
#> 10  31.0  16.5
#> ..   ...   ...

画图代码:

ggplot(plot_2d,aes(v1,v2)) +
  geom_bin2d(bins = 20)+
  geom_hline(yintercept = mean(plot_2d$v2,na.rm = T),colour="white",size=1)+
  geom_vline(xintercept = mean(plot_2d$v1,na.rm = T),colour="white",size=1)+
  labs(fill="COUNT",
       title="二维密度图",
       x="维度1",
       y="维度2")+
  theme_classic()+
  theme(text=element_text(family = "myfont"),
        title=element_text(family = "myfont",face="bold"))

二维密度图