R使用筆記: ggplot2

本筆記內(nèi)容:
最近工作中遇到的分析需求:按照要求的分組畫boxplotPcoA的散點(diǎn)圖疟羹。對畫各種圖的實(shí)現(xiàn)方法,一些具體問題的解決方法等也祠。

  • Long data和wide data之間的轉(zhuǎn)換, 及其作用
  • 作圖細(xì)節(jié):box的顏色冷离,散點(diǎn)分布,調(diào)整label的角度, 修改label: theme(), labs()等
  • 調(diào)整橫坐標(biāo)labels的順序:設(shè)置factor中l(wèi)evel的順序
  • facet_grid(): 將一個(gè)Plot按照分組繪制多個(gè)Plot搏屑,并在theme()中設(shè)置它的屬性
  • ggplot2的一些通用規(guī)律
  • PCoA:ade4和ggplot2
  • legend()用法
  • theme()快捷設(shè)置
  • 零碎的東西
  • 在boxplot之間連線
  • geom_bar()
  • geom_, geom_, geom_
  • scale_, scale_, scale_
  • error bar
  • 在geom_boxplot()中去掉outlier
  • 拼圖之后加上一個(gè)總title
  • ggexport
  • ggsignif
  • geom_boxplot()畫出來的box釋義
  • stacked barchart和percentage stacked barchart
  • sankey flow
long data和wide data之間的轉(zhuǎn)換, 及其作用

關(guān)于Long data和wide data之間的轉(zhuǎn)換及其意義,我寫過在python中的用法粉楚,見python學(xué)習(xí):pandas學(xué)習(xí)筆記(三)中Pandas.melt()的用法辣恋。在這里是用R實(shí)現(xiàn)亮垫。一般ggplot2需要使用Long data. 比方說如下所示的數(shù)據(jù)cond1, cond2control你都想用ggplot2畫boxplot出來,那必須轉(zhuǎn)化為Long data, 把每個(gè)樣本的測量值分一列伟骨,測得是cond1還是cond2一列饮潦。
了解更多參考這個(gè)鏈接

t <- read.table(header=TRUE, text='
  subject sex control cond1 cond2
        1   M     7.9  12.3  10.7
        2   F     6.3  10.6  11.1
        3   F     9.5  13.1  13.8
        4   M    11.5  13.4  12.9
 ')

t_long <- melt(t, id.vars = c('subject', 'sex')) # id.vars為不合并的列,即保留的列
t_long
   subject sex variable value
1        1   M  control   7.9
2        2   F  control   6.3
3        3   F  control   9.5
4        4   M  control  11.5
5        1   M    cond1  12.3
6        2   F    cond1  10.6
7        3   F    cond1  13.1
8        4   M    cond1  13.4
9        1   M    cond2  10.7
10       2   F    cond2  11.1
11       3   F    cond2  13.8
12       4   M    cond2  12.9
作圖細(xì)節(jié):box的顏色携狭,散點(diǎn)分布等

以以上數(shù)據(jù)為例继蜡,按照variable的分組畫三個(gè)boxplot:

ggplot(t_long, aes(x = variable, y = value)) + 
      geom_boxplot()
ggplot(t_long, aes(x = variable, y = value, fill = variable))  +  
     geom_boxplot() + geom_point(position = position_jitterdodge()) + 
     # 在box中加上點(diǎn),讓點(diǎn)隨機(jī)排列逛腿,不要忘記用加號銜接
     
     scale_fill_brewer(palette = "Set3") +   # 使用brewer.pal中的調(diào)色盤
    
     theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
     # theme()用來設(shè)置labels, 以及l(fā)abels與各軸之間的角度
    
     labs(x = "condition", y = "condition_values")
     # 重命名labels

ggplot(t_long, aes(x = variable, y = value, fill = sex))  +  
     geom_boxplot(position = position_dodge(0.8)) + 
     # 因?yàn)榘汛骲oxplot拆分成兩個(gè)稀并,設(shè)置這兩個(gè)小boxplot之間的距離
     geom_point(position = position_jitterdodge()) + 
     scale_fill_brewer(palette = "Set3") +   
     theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + 
     labs(x = "condition", y = "condition_values")
 # ggplot(aes(fill = ))變化了,將每個(gè)variable拆分成sex的兩個(gè)小組畫圖


可以參考這個(gè)鏈接单默,一個(gè)基礎(chǔ)又詳細(xì)的教程碘举。

調(diào)整橫坐標(biāo)labels的順序:設(shè)置factor中l(wèi)evel的順序
c <- t_long$value
t_long$variable <- factor(t_long$variable ,
     levels =unique(t_long$variable[order(-c)]))
# 讓整個(gè)boxplot大致降序排列,需要將包含box類別的變量設(shè)置為factor,在level中設(shè)置為按照值來降序排列
# ....真是麻煩啊...如果有什么別的好辦法還請告訴我

將boxplot降序或者升序排列搁廓,在fill = 變量非常多引颈,把整個(gè)圖拉的很長的情況下很有用,可以很明確的看出數(shù)據(jù)的規(guī)律境蜕。最好能在input dataframe的時(shí)候就把數(shù)據(jù)整理成一定順序蝙场。

還有一個(gè)辦法:

ggplot(t_long, aes(x = reorder(variable, value, FUN = median)), y = ...)
# 在ggplot的aes()里指定按照中位數(shù)大小排列
facet_grid():將一個(gè)Plot按照分組繪制多個(gè)Plot

使用一個(gè)R自帶的數(shù)據(jù)集為例:data(ToothGrowth),這個(gè)數(shù)據(jù)集有兩個(gè)分組汽摹,一個(gè)是supp, 一個(gè)是dose, 記得需要先把dose轉(zhuǎn)化為factor再行后續(xù)操作李丰。

t <- data(ToothGrowth)
t$dose <- as.factor(t$dose)
p2 <- ggplot(t, aes(x = supp, y = len, fill = supp)) +
  geom_boxplot(position = position_dodge(0.8)) +
  geom_point(position = position_jitterdodge()) +
  scale_fill_brewer(palette = "Set3") +
  facet_grid(dose ~ .,scales = "free") +     # 按照dose的分組將plot分成3個(gè)不同的dose子plot; scales的意思是按照各分組數(shù)據(jù)的極限值設(shè)置各子plot的scale, 不統(tǒng)一苦锨。
  theme(axis.title = element_text(size = 15), 
        axis.text.x = element_text(size = 15), 
        axis.text.y = element_text(size =12),
        strip.text.y = element_text(size = 12),     # 調(diào)整不同子plot的標(biāo)簽字體大小
        panel.spacing = unit(1, "lines")) +         # 調(diào)整不同子plot之間距離大小
  labs(x = "", y = "")
不設(shè)置facet_grid的圖
設(shè)置facet_grid形成子plot

更多參考以下鏈接:
http://www.sthda.com/english/wiki/ggplot2-customize-how-to-personalize-easily-ggplot2-graphs-in-r-statistical-software
http://www.sthda.com/english/wiki/ggplot2-facet-split-a-plot-into-a-matrix-of-panels

ggplot2的一些通用規(guī)律
ggplot(dataframe, aes(x = X, y = Y, fill = group, color = group)) +      
  # 設(shè)置了fill則將"可以fill的形狀"填充起來逼泣,比方說橢圓,比方說boxplot, barplot等舟舒。不設(shè)置fill什么顏色則ggplot2默認(rèn)填充拉庶。用scale_fill_**設(shè)置填充顏色
  # color用于設(shè)置點(diǎn)或者線的顏色,比方說boxplot的外框描線...

  + geom_point(aes(color = group), alpha = 0.8, size = 4) 
  # 在aes()中設(shè)置點(diǎn)的顏色秃励,但是點(diǎn)的透明度氏仗,大小等屬性注意在aes()之外設(shè)置
  # 在aes()之外,position = position_jitterdodge()將點(diǎn)按照分組分開

  + geom_boxplot()
  + scale_color_manual(values = c(xxx,xxx,xxx...))
  # scale_color_**用于自定義color的顏色夺鲜,即點(diǎn)皆尔,線的顏色

  + scale_fill_manual(values = c(xxx, xxx, xxx...))
  # scale_fill_**用于自定義fill的顏色,即填充顏色

PCoA:ade4和ggplot2

ade4包:以距離矩陣為input, 用cmdscale()獲取坐標(biāo)軸位置币励,用s.class畫圖并按照分組聚類慷蠕。可是沒有坐標(biāo)軸信息食呻,也不知道這兩維分別可以有多少variance explained

unifrac <- read.table(...)
meta <- read.csv(...)

mds <- cmdscale(unifrac,k = 2, eig = TRUE)

mds_m <- mds$points
group <- as.factor(meta$grouping)  # 把分組信息轉(zhuǎn)化為Factor
plot_color <- brewer.pal(5,"Set2")[group]   # 便于給每個(gè)樣本分組并上色
s.class(mds_m, col=unique(plot_color), cpoint = 1, fac = group, cstar = 1, cellipse = 1) 
# 按照分組形成聚類橢圓(wheel)
# 用fake data畫的

ggplot2包:需要把metadata和cmdscale()得到的mds坐標(biāo)合并為一個(gè)dataframe作為input, 并使用上面ade4包得到的mds$eig計(jì)算variance explained
可以參考一篇宏基因組公眾號的文章: 擴(kuò)增子統(tǒng)計(jì)繪圖2散點(diǎn)圖:Beta多樣性

eig <- mds$eig
mds_df <- data.frame(mds_m)
mds_meta <- cbind(mds_df, meta)

# X1, X2為各點(diǎn)坐標(biāo)信息的col_name流炕,grouping為分組信息的col_name
# 都在mds_meta中

ggplot(mds_meta, aes(x = X1, y = X2)) +
  geom_point(aes(color = factor(grouping)), size = 3) +
  scale_color_discrete(name = "grouping") +
  stat_ellipse(aes(x = X1, y = X2, color = grouping), type = "norm") +
  labs(x = paste("PCoA 1 (", format(100*eig[1]/sum(eig), digits = 4), "%)",sep = ""), 
       y = paste("PCoA 2 (", format(100*eig[2]/sum(eig), digits = 4), "%)",sep = "")
  )
# 手動(dòng)添加variance explained的label
legend()用法
group <- as.factor(data$group)
color <- brewer.pal(length(levels(group)), "Set1")

heatmap.2(x...)

par(lend = 1)
legend(0.88, 0.998,  # 也可以直接指定:“bottomright”, “bottom”, “bottomleft”, “l(fā)eft”, “topleft”, “top”, “topright”, “right”, “center”
       legend = levels(group),    # 指定legend中寫什么字
       col = color,  #指定顏色
       lty = 1,      # 顯示為直線型色塊
       lwd = 10,     # 顯示色塊的寬度
       text.col = "black"澎现,# legend字體顏色
       pch = c(.., .., .....)  # 如果你的legend lty沒有設(shè)置,想設(shè)置成不同形狀不同顏色的legend每辟,則使用pch指定色塊的形狀剑辫,具體代碼對應(yīng)的形狀見下圖
       cex = 0.8)    # 設(shè)置字體大小
pch對應(yīng)的具體形狀

參考連接:https://www.rdocumentation.org/packages/graphics/versions/3.5.0/topics/legend

theme()快捷設(shè)置

default為+ theme_gray()
常用 theme_classic(), 詳見以下鏈接
http://ggplot2.tidyverse.org/reference/ggtheme.html
theme_classic(size = n)設(shè)置默認(rèn)classic的主題中字體大小

如何去掉legend title/legend

ggplot() + theme(legend.title=element_blank())
theme(legend.position = "none")則去除legend

給boxplot加上統(tǒng)計(jì)檢驗(yàn)結(jié)果及P值

https://www.r-bloggers.com/add-p-values-and-significance-levels-to-ggplots/

ggarrange() 把圖組合在一起,公用legend

ggarrange(plotlist = plot_list, ncol = 4, common.legend = TRUE)
如果有一個(gè)list of plots, 可以用ggarrange(plotlist...)
合并在一起渠欺,且可以公用legend, 設(shè)置legend的位置妹蔽。

boxplot(fill = )和scale_fill_manual()

往往要在boxplot(fill=)中設(shè)置了顏色才可以顯示!那要scale_fill_manul多么雞肋挠将!要你何用讹开!

在boxplot之間連線

詳見這個(gè)鏈接

ggplot(..) +
   geom_line(aes(group = interaction(index, variable)) +...
# index將要連接的點(diǎn)聯(lián)系在一起 
geom_bar()

geom_bar(position = 'fill'/'dodge')
舉個(gè)栗子:

library(socviz) # 用這里的gss_sm數(shù)據(jù)集
ggplot(data= gss_sm, aes(x=bigregion,fill=religion)) + 
  geom_bar(position='fill')

ggplot(data= gss_sm, aes(x=bigregion,fill=religion)) + 
  geom_bar(position='dodge')

分別得到:

另外:

  1. geom_bar()geom_histogram()的區(qū)別:
    histogram用于查看單個(gè)變量的distribution,當(dāng)然也可以把幾個(gè)變量的distribution放在一張圖里捐名,比較他們的分布旦万。
    bar圖用于查看多個(gè)變量的計(jì)數(shù)/占比/數(shù)值大小。
  2. geom_bar(stat = "identity")geom_col() 是一樣的镶蹋,都表示把對應(yīng)的y值直接plot出來成艘,不用做任何stat summary
geom_,geom_,geom_...

geom_dotplot()
geom_smooth() 平滑曲線,或者線性的直線
geom_pointrange(ymin=.. ,ymax=...) 給點(diǎn)加上range,比方說Sd, 你必須先準(zhǔn)備好sd的數(shù)據(jù)贺归,不能指望ggplot2給你做好淆两。這里可以注意與dplyr的結(jié)合使用,提高效率拂酣,減少中間變量秋冰。
facet_wrap(~ variable, scales = "free_y", ncol = 1) 注意scales的用法

scale_, scale_,scale_

ggplot(aes(...))的完整是ggplot(mapping = aes(x = .., y =.., color = ..., fill = ... ...)), 每個(gè)mapping中的東西,都具有一個(gè)scale. x和y是連續(xù)型變量婶熬,其scale交給scale_x_log10(), scale_x_continuous()來調(diào)整剑勾。像mapping中的color, fill ,shape等, 需要scale_color_discrete()等來調(diào)整赵颅,比如以下這個(gè)例子:

library(socviz)
data(organdata) # 示例數(shù)據(jù)
ggplot(organdata, aes(x=roads, y= donors, color= world)) +
    geom_point() 

ggplot(organdata, aes(x=roads, y= donors, color= world)) +
    geom_point() +
    scale_color_discrete(labels = c("Corporatist", "Liberal", "Social Democratic", "Unclassified")) + 
    labs(x = "Road Deaths", y = "Donor Procurement", color = "Welfare State")

# scale_color_manual(name = "XXX", values = XXXcolors)
error bar

在ggplot2中實(shí)現(xiàn)有很多種方法虽另,包括:
geom_pointrange()
geom_linerange()
geom_crossbar()
geom_errorbar()

在geom_boxplot()中去掉outlier

geom_boxplot(outlier.shape = NA) + ...

拼圖之后加上一個(gè)總title
annotate_figure(ggarrange(plotlist = plotlist))
ggexport

ggexport %>%與ggplot2的object無縫銜接

ggarrange(...) %>%
    ggexport(filename=XXX,height=XX, width=XXX)
ggsignif (geom_signif())
ggplot(...) +
  geom_signif(test = 'wilcox.test',
              comparisons = XXX,
              vjust=0,  # significant level橫線和P值數(shù)字之間的距離
              textsize = 6, # p值數(shù)字的大小
              size=0.5, # 橫線的粗細(xì)程度
              step_increase=0, # 根據(jù)bar的總長度的一定比例,確定每個(gè)significant level要上升多少
              y_position = XXX, # c(), 固定好每個(gè)significant level的y軸坐標(biāo)饺谬,推薦使用這個(gè)
              annotations = XXX  # P值內(nèi)容捂刺,也可以換成*,**,***...
              )
geom_boxplot()畫出來的box釋義

參考:https://waterdata.usgs.gov/blog/boxplots/

stacked barchart和percentage stacked barchart
# 數(shù)據(jù):
specie <- c(rep("sorgho" , 3) , rep("poacee" , 3) , rep("banana" , 3) , rep("triticum" , 3) )
condition <- rep(c("normal" , "stress" , "Nitrogen") , 4)
value <- abs(rnorm(12 , 0 , 15))
data <- data.frame(specie,condition,value)
ggplot(data,aes(fill=condition,y=value,x=specie))+
  geom_bar(position = 'fill',stat = 'identity')
ggplot(data,aes(fill=condition,y=value,x=specie))+
  geom_bar(position = 'dodge',stat = 'identity')


參考這個(gè)連接

sankey flow

https://cran.r-project.org/web/packages/ggalluvial/vignettes/ggalluvial.html
http://corybrunson.github.io/ggalluvial/reference/geom_flow.html
https://stackoverflow.com/questions/9968433/sankey-diagrams-in-r

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市募寨,隨后出現(xiàn)的幾起案子族展,更是在濱河造成了極大的恐慌,老刑警劉巖拔鹰,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仪缸,死亡現(xiàn)場離奇詭異,居然都是意外死亡格郁,警方通過查閱死者的電腦和手機(jī)腹殿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門独悴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锣尉,你說我怎么就攤上這事刻炒。” “怎么了自沧?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵坟奥,是天一觀的道長。 經(jīng)常有香客問我拇厢,道長爱谁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任孝偎,我火速辦了婚禮访敌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘衣盾。我一直安慰自己寺旺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布势决。 她就那樣靜靜地躺著阻塑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪果复。 梳的紋絲不亂的頭發(fā)上陈莽,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機(jī)與錄音虽抄,去河邊找鬼走搁。 笑死,一個(gè)胖子當(dāng)著我的面吹牛极颓,可吹牛的內(nèi)容都是我干的朱盐。 我是一名探鬼主播群嗤,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼菠隆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狂秘?” 一聲冷哼從身側(cè)響起骇径,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎者春,沒想到半個(gè)月后破衔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钱烟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年晰筛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嫡丙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡读第,死狀恐怖曙博,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情怜瞒,我是刑警寧澤父泳,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站吴汪,受9級特大地震影響惠窄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜漾橙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一杆融、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧霜运,春花似錦擒贸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至案淋,卻和暖如春座韵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背踢京。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工誉碴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓣距。 一個(gè)月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓黔帕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蹈丸。 傳聞我的和親對象是個(gè)殘疾皇子成黄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容