查看原文
其他

是Excel的图,不!是R的图

易生信 生信宝典 2022-03-29
原文章来源链接:https://brucezhaor.github.io/blog/2016/06/13/excel2ggplot/
原文章作者:BruceZhaoR(RStats, interested in Statistics Models, Machine/Deep Learning, Data visualization, High Performance Computing ...)
作者主页:https://github.com/BruceZhaoR

excel作为一个强大的统计工具,自身包含着一部分数据可视化的功能。R作为可视化的大势,自然也可以画出这些图,有一篇就通过ggplot2包进行了部分总结,甚是有趣,小编复刻学习了一番,现对代码做简单注释,以作分享。


关于excel,ppt,你还可以get

Excel改变了你的基因名,30% 相关Nature文章受影响,NCBI也受波及

推荐 3 个超赞的 EXCEL 插件,让你 5 分钟从小白变大神

你和PPT高手之间,就只差一个iSlide


加载所需工具包

library(ggplot2) #作图包
library(dplyr) #数据转换包
library(tidyr) #数据转换包
library(splines) #数据差值包

ggplot2的基本概念

数据data/映射美学asethetics/几何对象geometries/分面facets/统计statistics/坐标系coordinates/主题themes

数据准备

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) #显示数据

得到所需数据样式(宽矩阵转长矩阵)

df1<- df%>%gather("item",value,-1:-2)%>% bind_cols(data.frame(item_id=rep(1:3,each=10)))

# 使用tidyr和dplyr包的gather函数进行数据样式转换,%>%是dplyr包的传递函数

print(df1)

ggplot画图

ggplot2是图层式绘图,一层层添加修改,图层需要指定数据集,数据集中的内容(ase数据),geom_图形,stat统计转换,position图形位置

柱形图——geom_bar,注意position参数

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
labs(title="柱形图") # geom_bar=stat_count,stat=identy接受两个变量作图,position默认参数是stack,position="dodge"时,不同变量横向排列

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=(item)),stat = "identity",position="stack",width=0.8)+
labs(title="堆积柱状图")

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="fill",width=0.8)+
labs(title="百分比堆积柱状图")

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",width=0.8)+
facet_grid(item~.)+ # 垂直方向分割
labs(title="三维柱形图") # 平面展示,(facet_grid)将三维图平面展示

折线图——geom_line

变量以点展示,然后连点成线ggplot(df1,aes(id,value,colour=item))+ # 点
geom_line()+ # 连线
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+ #将X坐标轴改为十等分并标以字母
labs(title="折线图")

ggplot(df1,aes(id,value,colour=item))+
geom_line(position="stack")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title="堆积折线图")

ggplot(df1,aes(id,value,colour=item))+
geom_line(position="fill")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title="百分比堆积折线图")

ggplot(df1,aes(id,value,colour=item))+
geom_line()+
geom_point()+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title="带标记的折线图") #增加了散点图geom_point

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])+
labs(title="带标记的堆积折线图")

ggplot(df1,aes(id,value,colour=item))+
geom_line(aes(ymin=0),position="fill")+
geom_point(aes(ymin=0),position="fill")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title="带标记的百分比堆积折线图")


ggplot(df1,aes(id,value,colour=item))+
facet_grid(item~.)+ # 垂直方向分割
geom_line()+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title="三维折线图") #用facet_grid平面展示,

饼图

饼图,将一般的柱图进行直角坐标轴到极坐标轴的转换(coord_polar())

ggplot(df,aes(x=factor(1),a,fill=factor(var)))+
geom_bar(stat="identity",position="fill")+
coord_polar(theta="y")+ # 按Y轴极坐标转换
labs(title="饼图")因为是在条形图中对y轴进行极坐标转换,因此x轴长短需要一致,统一设为一个值,此处是x=factor(1)

复合饼图和复合条饼图

有嵌套类时,可以衍生一个图形展现子类内容,下图是一个demo,仅作为图案参考样式,还有许多需要改进的地方

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)+ # 图左
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)+ # 图右
annotate("segment",x=0.5,xend=1.5,
y=0.69,yend=0.77)+ # 下线条
annotate("segment",x=0.5,xend=1.5,
y=1.35,yend=1.28) # 上线条+
labs(title="复合饼图")

# 复合条饼图

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="复合条饼图")

圆环图

一个圆环代表一个变量,颜色表示其属性

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

其他圆形图

用coord_polar作出的demo图

demo1<-ggplot(df,aes(x = factor(1),a,fill=factor(var)))+
geom_bar(stat="identity",position="dodge")
demo1 #柱形图

demo1+coord_polar(theta="y") # 按y轴极坐标转换

demo1+coord_polar(theta="x") # 按X轴极坐标转换,此时x还可以等于var

demo2<-ggplot(df1,aes(x = id,value,fill=item))+
geom_bar(stat="identity",position="fill",width=0.8)
demo2 # 百分比柱形图

demo2+coord_polar(theta="x") # 按x轴极坐标转换

条形图

条形图就是横过来的柱形图,用函数coord_filp()处理逆时针旋转90°

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
labs(title="条形图")+
coord_flip() # 和柱形图代码的唯一区别coord_flip()

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="stack",width=0.8)+
labs(title="堆积条形图")+
coord_flip()

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="fill",width=0.8)+
labs(title="百分比堆积条形图",fill="")+
coord_flip()

ggplot(df1,aes(var,value))+
geom_bar(aes(fill=item),stat = "identity",position="dodge",width=0.8)+
labs(title="三维百分比条形图",fill="")+
coord_flip()+
facet_grid(.~item) # 水平方向分割,用多个分面展示多维

面积图——geom_area

面积图就是将折线图下面的区域标注颜色,表示面积。

ggplot(df1,aes(id,value))+
geom_area(aes(fill=item),position=position_dodge(width = 0),
alpha=0.5)+ # 暗色不透明度
labs(title="面积图",fill="")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

ggplot(df1,aes(id,value))+
geom_area(aes(fill=item),alpha=0.5)+
labs(title="堆积面积图")+ # 区别堆积折线图是少了`position=stack`
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

ggplot(df1,aes(id,value))+
geom_area(aes(fill=item),position="fill",alpha=0.5)+
labs(title="百分比堆积面积图",fill="")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])

ggplot(df1,aes(id,value))+
geom_area(aes(fill=item),position="stack",alpha=0.5)+
# 区别于三维折线图添加了`position=stack`,便于分割后更好观察面积分布
labs(title="三维百分比堆积面积图",fill="")+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
facet_grid(item~.) # 按垂直水平分割

XY散点图

需要注意的是确定X,Y轴以后,需要把对应的值赋到图中

ggplot(df1,aes(var,value))+
geom_point(aes(colour=item))+
labs(title = "散点图")

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()
# 分开获得需要a,b,c的数据value,并被等分为1000份,用spline曲线连接,转换为数据框格式

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

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])+
labs(title = "带平滑线和数据标记的散点图") # 点加线

ggplot(df1,aes(id,value,colour=item))+
geom_point()+
geom_line()+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title = "带直线和点数据标记的散点图")

ggplot(df1,aes(id,value,colour=item))+
geom_line()+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
labs(title = "带直线的散点图") # 就是折线图

气泡图

气泡图即点的大小表示数值大小的点图

ggplot(df1,aes(id,value,colour=item))+
geom_point(aes(size=value))+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])
# `size=value`给点赋予数值大小属性

股价图

ggplot(df)+
geom_point(aes(Sys.Date()-1:10,c))+
geom_linerange(aes(Sys.Date()-1:10,ymin=a,ymax=b))+
labs(title="已知盘高-盘低-收盘图")

# `Sys.Date`返还任一日期时间,c是收盘量
# `geom_linerange`是由a,b两个对象的ymin和ymax定义的垂直区间线图

ggplot(df)+
geom_point(aes(Sys.Date()-1:10,c))+
geom_linerange(aes(Sys.Date()-1:10,ymin=a,ymax=b))+
geom_crossbar(aes(Sys.Date()-1:10,c,ymin=a,ymax=c),width=0.2)+
labs(title="已知开盘-盘高-盘低-收盘图")

# 在已知盘高-盘底-收盘图的基础上加上`geom_crossbar`,这里是连系a的最小和c的最大值,
# geom_crossbar(): 空心柱,上中下三条线分别代表ymax,mean,ymin

ggplot(data = filter(df1,item != "c"),
aes(rep(Sys.Date()-1:10,3),value))+
facet_grid(item~.,scale="free")+
geom_point(data = filter(df1,item == "a"),
aes(Sys.Date()-1:10,value))+
geom_linerange(data = filter(df1,item == "a"),
aes(Sys.Date()-1:10,value,
ymin=value-runif(10),
ymax=value+runif(10)))+
geom_bar(data = filter(df1,item == "b"),
aes(Sys.Date()-1:10,value*1000),
stat="identity")+
labs(title="成交量-盘高-盘低-收盘图")

# 点和线距图是对象a的数据有盘高盘低,条形图是关于对象b的图,成交量
# facet_grid(item~.,scale="free"),垂直分割,且不同形式的图表可以被分割出来

ggplot(data = filter(df1,item != "c"),
aes(rep(Sys.Date()-1:10,3),value))+
facet_grid(item~.,scale="free")+
geom_point(data = filter(df1,item == "a"),
aes(Sys.Date()-1:10,value))+
geom_linerange(data = filter(df1,item == "a"),
aes(Sys.Date()-1:10,value,
ymin=value-runif(10),
ymax=value+runif(10)))+
geom_crossbar(data = filter(df1,item == "a"),
aes(Sys.Date()-1:10,value,
ymin=value-runif(10),
ymax=value+runif(10)),
width=0.2)+
geom_bar(data = filter(df1,item == "b"),
aes(Sys.Date()-1:10,value*1000),
stat="identity")+
labs(title="已知成交量-开盘-盘高-盘低-收盘图")

# 在上一个图的基础上加了个`geom_crossbar`,筛选对象b作为开盘

曲面图——geom_contour

三维图形,下图是对密度的一个二维密度估计

ggplot(df1,aes(id,item_id))+
geom_contour(aes(z=value,colour=..level..),
binwidth=0.001)+
scale_colour_gradientn(colours = terrain.colors(10))+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
scale_y_continuous(breaks = 1:3,labels = letters[1:3])+
labs(title="曲面图")

# binwidth设置组距,值越小画得线越多,密度图函数colour设置等高线颜色

ggplot(df1,aes(id,item_id))+
geom_contour(aes(z=value,colour=..level..),
binwidth=0.1)+
scale_colour_gradientn(colours = terrain.colors(10))+
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+
scale_y_continuous(breaks = 1:3,labels = letters[1:3])+
labs(title="曲面图(框架图)")

# 用不同颜色等高线画框架图,和上图比增加了组距。

雷达图

ggplot(df1,aes(id,value,colour=item))+
geom_bar(stat="identity",
position="dodge", # 普通柱形图
fill="transparent",# 填充透明度
size=1)+
coord_polar()+ #极坐标转换
scale_x_continuous(breaks = 1:5,labels = LETTERS[1:5])+
facet_wrap(~item,nrow=2)+ # 水平分割,分割后的图呈两行排列
labs(title="雷达图")

# 雷达图就是极坐标转换后的普通柱形图,加了透明背景框,相当于其他透明图


ggplot(df1,aes(id,value,colour=item))+
geom_bar(stat="identity",
position="dodge",
fill="transparent",
size=1,
width=0.5)+
geom_point()+
coord_polar()+
scale_x_continuous(breaks = 1:5,labels = LETTERS[1:5])+
facet_wrap(~item,nrow=2)+
labs(title="带数据标记的雷达图")

# 在geom_bar的基础上加上了以三个对象a,b,c,的值为点的点图geom_point

ggplot(df1,aes(id,value))+
geom_bar(aes(fill=item),stat="identity",
position="dodge")+ # 以item项的值映射柱形图的表达值
scale_x_continuous(breaks = 1:10,labels = LETTERS[1:10])+ # x轴分成了十等份
coord_polar()+
facet_wrap(~item,nrow=2)+
labs(title="填充雷达图")

直方图

直方图是先把数据划分区间,按从小到大的顺序排列,并以柱状图的形式表现

ggplot(df1,aes(value))+
geom_histogram(bins=5,colour="white") # 映射value表达值,边界框是白色

# 排列图(数据从小到大排列)

df_tmp2<-df %>% select(1:3) %>% # 前三列
arrange(a) %>% #按列a的值从小到大排序
mutate(per = a/sum(a)) %>% # 增加per列,值为对应总数的比例
arrange(desc(a)) %>% # 重新按列a的值从达到小排列
mutate(new_id = 1:10)%>% # 增加new_id列
mutate(per = cumsum(per)) # 将per列的值按new_id的顺序逐个叠加

ggplot(df_tmp2)+
geom_bar(aes(new_id,a,fill=var),stat="identity")+ # fill=var添加图例并按照图例上色
geom_line(aes(new_id,per))+
scale_x_continuous(breaks = 1:10,
labels = df_tmp2$var)
# 令X轴的值为df_tmp2的var

箱型图

箱型图是用分位数表述数据的离散和集中趋势

ggplot(df1,aes(item,value,colour=item))+
geom_boxplot(aes(fill=item),alpha=0.2,
outlier.colour = "red",
outlier.shape = 2,
outlier.size = 5,
coef=1.5)+ # 箱线图的异常值设定,边框为红色,形状为2指代的三角形,大小为5,参数coef指定了“须”的长度的极限值,默认值是1.5,表示两条须的极限不会超过盒型各端加1.5倍四分位距的范围,如果被置为0,条须的延长极限就会在数据集中元素的极限位置,图中不会有任何离群点。geom_jitter(width = 0.1) # geom_jitter()是geom_point(position="jitter")的简称,带状图,一维散点图。

 瀑布图

瀑布图可表现图形涨跌趋势,后一个柱子和前一个柱子有增长和下降的关系。

df_tmp3 <- df %>%select(1:3)%>%mutate(cum=cumsum(a) ,low=lag(cum,default = 0)) 
# 新增一列cum,值为对应a值逐个叠加,新增加一列low,对应的是同一行的cum的上一个值,开始值是0.

ggplot(df_tmp3,aes(id,cum))+
# geom_step(colour="grey50")+ 是梯线
geom_crossbar(aes(ymin=low,ymax=cum),
size=0,
fill="skyblue",
colour="grey50", # 边框颜色
width=1)+
scale_x_continuous(breaks = 1:10,
labels = LETTERS[1:10]) #geom_crossbar(): 空心柱,上下两条线分别代表ymax、ymin

漏斗图

漏斗图的数据分布在图形中间,用coord_flip()转换方向,可以看到不同组的最大,最小值的差异

df_tmp4<-df %>% select(1:3) %>%
arrange(a) %>%
mutate(new_id=1:10,
ymin = (1-a)/2,
ymax = a+(1-a)/2,
mid = 0.5) # 新增四列,new_id,ymin,ymax和min列

ggplot(df_tmp4,aes(new_id,mid))+
# geom_step(colour="grey50")+
geom_crossbar(aes(ymin=ymin,ymax=ymax),
size=0,
fill="skyblue",
colour="grey50",
width=1)+
scale_x_continuous(breaks = 1:10,
labels = df_tmp4$var)+
coord_flip() # 整个图形逆时针转90度

# geom_crossbar()空心柱

ggplot(df_tmp4,aes(new_id,mid))+
geom_linerange(aes(ymin=ymin,ymax=ymax,
colour=factor(new_id)),
size=15,
alpha=0.5,show.legend = F)+
scale_x_continuous(breaks = 1:10,
labels = df_tmp4$var)+
coord_flip()

高颜值在线免费绘图


R统计和作图

ggplot2高效实用指南 (可视化脚本、工具、套路、配色)

ggplot2学习笔记之图形排列

你的包佩奇了吗?试试新版Rstudio,自动提醒缺失包!

原来Rstudio还可以这么使用,又方便了一些

在R中赞扬下努力工作的你,奖励一份CheatShet

别人的电子书,你的电子书,都在bookdown

R语言 - 入门环境Rstudio

R语言 - 热图绘制 (heatmap)

R语言 - 基础概念和矩阵操作

R语言 - 热图简化

R语言 - 热图美化

R语言 - 线图绘制

R语言 - 线图一步法

R语言 - 箱线图(小提琴图、抖动图、区域散点图)

R语言 - 箱线图一步法

R语言 - 火山图

R语言 - 富集分析泡泡图

R语言 - 散点图绘制

R语言 - 韦恩图

R语言 - 柱状图

R语言 - 图形设置中英字体

R语言 - 非参数法生存分析

R语言 - 绘制seq logo图

一文学会网络分析——Co-occurrence网络图在R中的实现

R中1010个热图绘制方法

图像处理R包magick学习笔记

R语言可视化学习笔记之ggridges包

R包reshape2,轻松实现长、宽数据表格转换

用R在地图上绘制网络图的三种方法

PCA主成分分析实战和可视化 附R代码和测试数据

iTOL快速绘制颜值最高的进化树!

12个ggplot2扩展包帮你实现更强大的可视化

编程模板-R语言脚本写作:最简单的统计与绘图,包安装、命令行参数解析、文件读取、表格和矢量图输出

R语言统计入门课程推荐——生物科学中的数据分析Data Analysis for the Life Sciences

数据可视化基本套路总结

你知道R中的赋值符号箭头<-和等号=的区别吗?

使用dplyr进行数据操作30例

R包reshape2,轻松实现长、宽数据表格转换

R语言搭建炫酷的线上博客系统

R包circlize:柱状图用腻了?试试好看的弦状图

获取pheatmap聚类后和标准化后的结果

增强火山图,要不要试一下?

一个震撼的交互型3D可视化R包 - 可直接转ggplot2图为3D

赠你一只金色的眼 - 富集分析和表达数据可视化


易生信系列培训课程,扫码获取免费资料

更多阅读

画图三字经 生信视频 生信系列教程 

心得体会 TCGA数据库 Linux Python 

高通量分析 免费在线画图 测序历史 超级增强子

生信学习视频 PPT EXCEL 文章写作 ggplot2

海哥组学 可视化套路 基因组浏览器

色彩搭配 图形排版 互作网络

自学生信 2019影响因子 GSEA 单细胞 

后台回复“生信宝典福利第一波”或点击阅读原文获取教程合集


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存