編程筆記6-dplyr常用語法

引言

一直以來都聽聞tidy-r是使R語言起死回生的存在系枪,盡管沒有系統(tǒng)學(xué)習(xí)過,但已經(jīng)在coding中潛移默化的使用了許多tidy語法候生,例如管道符%>%桑包、ggplot2等等募壕。最近在處理bed文件時遇到了很多base-r解決起來非常復(fù)雜的問題调炬,網(wǎng)上一查都是用dplyr包解決的。因此本文記錄一下dplyr的常用語法舱馅,希望以后逐漸由base-r向tidy-r過渡缰泡。

tidyverse家族


dplyr函數(shù)特征

  1. 第一個參數(shù)是一個數(shù)據(jù)框。
  2. 隨后的參數(shù)描述了如何處理第一個參數(shù)中指定的數(shù)據(jù)框代嗤,你可以直接引用數(shù)據(jù)框中的列棘钞,而無需使用 $ 運(yùn)算符(只需使用列名)。
  3. 函數(shù)的返回結(jié)果是一個新的數(shù)據(jù)框
  4. 數(shù)據(jù)框必須經(jīng)過正確格式化和注釋才能發(fā)揮作用干毅。尤其是數(shù)據(jù)必須整齊宜猜。簡而言之,每一行應(yīng)該有一個樣本硝逢,每一列應(yīng)該代表那個樣本的特征姨拥。

篩選行:filter()

  • 例如,篩選出 1 月 1 日的所有航班
filter(flights, month == 1, day == 1)

這里渠鸽,flights是數(shù)據(jù)框叫乌,“month == 1, day == 1”是篩選條件,默認(rèn)是且的關(guān)系徽缚,還可以用其他條件進(jìn)行篩選:

filter(flights, month == 1 | day == 1)

排序行:arrange()

  • 按year, month, day的優(yōu)先級排列數(shù)據(jù)框flights
arrange(flights, year, month, day)
  • 如果有多個列名憨奸,那么就先按前面的列名排,然后在此基礎(chǔ)上排后面的列名
  • 默認(rèn)按升序排(從小到大)
  • 用 desc() 降序排凿试,如
arrange(flights, desc(arr_delay))
# 按arr_delay降序排宰,對觀測進(jìn)行重排
  • 缺失值總是排在最后

篩選列:select()

  • 選擇數(shù)據(jù)框flights中的year, month, day這幾列
select(flights, year, month, day)
  • 選擇“year”和“day”之間的所有列(包括“year”和“day”)
select(flights, year:day)
  • 選擇不在“year”和“day”之間的所有列似芝,記得帶括號
select(flights, -(year:day))
  • 可以在 select () 函數(shù)中使用一些輔助函數(shù),這些跟Excel中選擇名稱的規(guī)則類似
    starts_with("abc"):匹配 開頭是“abc” 的名稱额各。
    ends_with("xyz"):匹配 結(jié)尾是“xyz” 的名稱国觉。
    contains("ijk"):匹配 包含“ijk” 的名稱吧恃。
    matches("(.)\\1"):選擇匹配正則表達(dá)式的那些變量虾啦。這個正則表達(dá)式會匹配名稱中有重復(fù)字符的變量。
    num_range("x", 1:3):匹配 x1痕寓、 x2 和 x3傲醉。

  • 把 time_hour 和 air_time 移到數(shù)據(jù)框的開頭,其余按原來的順序呈現(xiàn)

select(flights, time_hour, air_time, everything())

重命名列:rename()

  • 將變量tailnum重命名為tail_num
rename(flights, tail_num = tailnum)

添加新列:mutate()

  • 添加新列:gain 和 speed呻率,并排在數(shù)據(jù)集的最后
mutate(flights,gain = arr_delay - dep_delay,speed = distance / air_time * 60) 
  • 新列一旦創(chuàng)建硬毕,就可立即使用。如在創(chuàng)建新列 gain_per_hour 的時候礼仗,用到了剛創(chuàng)建的新列 gain 和 hours
mutate(flights_sml,gain = arr_delay - dep_delay,hours = air_time / 60,gain_per_hour = gain / hours)
  • 如果只想保留新變量吐咳,可以使用 transmute() 函數(shù),如下代碼輸出結(jié)果中只有3列:gain 元践、 hours 和 gain_per_hour
transmute(flights,gain = arr_delay - dep_delay,hours = air_time / 60,gain_per_hour = gain / hours)
  • 輔助運(yùn)算符
    • 算術(shù)運(yùn)算符:+韭脊、 -、 *单旁、 /沪羔、 ^

    • 模運(yùn)算符:%/%(求整) 和 %%(求余),可以拆分整數(shù)象浑。

    • 對數(shù)函數(shù):log()蔫饰、 log2() 和 log10()。

    • 偏移函數(shù):lead() 返回序列領(lǐng)先值愉豺、 lag() 返回序列滯后值篓吁。

    • 累加和滾動聚合:cumsum() 累加和、 cumprod() 累加積蚪拦、commin() 累加最小值杖剪、 cummax() 累加最大值、cummean() 累加均值外盯,這幾個函數(shù)對于繪圖非常重要

    • 邏輯比較:<摘盆、 <=、 >饱苟、 >= 和 !=

    • 排秩:最常用的是min_rank() 孩擂,升序排,輸出結(jié)果是名次箱熬,如1 2 3 ... n类垦。


分組分析:group_by() 和 summarize()

  • 可以將數(shù)據(jù)框折疊成一行狈邑,如下代碼輸出為一個值,即所有航班的平均起飛延誤時間
summarize(flights, delay = mean(dep_delay, na.rm = TRUE))
  • 與 group_by() 聯(lián)用蚤认,即在分組基礎(chǔ)上進(jìn)行摘要統(tǒng)計米苹。group_by() 和 summarize() 聯(lián)用是 dplyr 包最常用的操作之一。
  • 如:將所有結(jié)果按method和benchmark分組砰琢,計算新分組的每組平均值蘸嘶,并用 n() 函數(shù)計數(shù),返回當(dāng)前分組的大小
> group_by(fig2a,method,benchmark) %>% 
+   summarise(mean = mean(value),
+             num = n()) 

# 輸出:
`summarise()` has grouped output by 'method'. You can override using the `.groups` argument.
# A tibble: 28 × 4
# Groups:   method [7]
   method       benchmark          mean   num
   <fct>        <fct>             <dbl> <int>
 1 scMAGIC-atac Accuracy          0.806     3
 2 scMAGIC-atac Average Recall    0.783     3
 3 scMAGIC-atac Average Precision 0.754     3
 4 scMAGIC-atac Mean F1           0.752     3
 5 GLUE         Accuracy          0.822     3
 6 GLUE         Average Recall    0.727     3
 7 GLUE         Average Precision 0.765     3
 8 GLUE         Mean F1           0.725     3
 9 Seurat       Accuracy          0.776     3
10 Seurat       Average Recall    0.666     3
# … with 18 more rows
  • 只使用均值陪汽、計數(shù)和求和是遠(yuǎn)遠(yuǎn)不夠的训唱, dplyr還提供了常見的摘要函數(shù),如:

    1. 位置度量:median(x) 中位數(shù)
    2. 分散程度度量:sd(x) 標(biāo)準(zhǔn)誤差挚冤、 IQR(x) 四分位距 和 mad(x) 絕對中位差
    3. 秩的度量:min(x)况增、max(x) 和 quantile(x, 0.25) 找出 x 中按從小到大順序大于前25% 而小于后 75% 的值
    4. 定位度量:first(x)、 nth(x, 2) 和 last(x)
    5. 計數(shù):n() 返回當(dāng)前分組的大小训挡, sum(!is.na(x)) 計算出非缺失值的數(shù)量澳骤, n_distinct(x) 計算出唯一值的數(shù)量,count()返回指定組合的計數(shù)
    6. 邏輯值的計數(shù)和比例:sum(x > 10) 找出 x 中 TRUE 的數(shù)量澜薄, mean(y == 0) 找出x 中 TRUE 的比例为肮。
  • 用 ungroup() 函數(shù)取消分組,并回到未分組的數(shù)據(jù)繼續(xù)操作


處理雙表格

  • 左鏈接left_join():以左邊的表的by變量為準(zhǔn)合并表悬,如果有數(shù)據(jù)缺失則顯示NA弥锄。
  • 右鏈接right_join():以右邊的表的by變量為準(zhǔn)合并,如果有數(shù)據(jù)缺失則顯示NA蟆沫。
  • 內(nèi)鏈接inner_join():返回兩個表中的交集部分籽暇。
  • 外鏈接full_join():返回兩表中的并集部分。

其他函數(shù)

  • add_count():給最后一列添加某列的counts數(shù)
  • distinct(col, .keep_all = T):只保留col不重復(fù)的行

實(shí)戰(zhàn)

  • 計算單細(xì)胞矩陣的TPM
mm10_gene <- read.table('/mdshare/node10/xyx/projects/RNA-editing/reference/genome_bed/mm10/mm10_gene.bed')
mm10_gene %>% 
  as_tibble() %>%                                       # df轉(zhuǎn)tibble
  transmute(gene_name = V6,                             # 新建一個tibble包含列g(shù)ene_name
            length = V3 - V2) %>%                       # 包含列l(wèi)ength為end - start
  group_by(gene_name) %>%                               # 按gene_name分組
  summarise(meanlen = round(mean(length))) %>%          # 計算每組的平均長度
  filter(gene_name %in% rownames(counts_mtx)) ->        # 篩選在query_mtx中的基因名
  counts_mtx_gene_len
counts_mtx_gene_len
counts_mtx <- counts_mtx[counts_mtx_gene_len$gene_name,]
counts_mtx_TPM <- apply(counts_mtx,2,function(col){col/counts_mtx_gene_len$meanlen}) %>% 
  NormalizeData()

總結(jié)

初次接觸tidyr會感覺函數(shù)的形參比較隨意饭庞,除了第一個參數(shù)必須是數(shù)據(jù)框本身戒悠,后續(xù)參數(shù)都沒有嚴(yán)格要求,有的參數(shù)還是函數(shù)名(例如之前一直不太理解的ggplot2中的aes())舟山。但實(shí)際上绸狐,這是因為tidyr的語法更多的是面向操作,而我之前使用的基于which()的篩選方法更多的是面向結(jié)果累盗。想想網(wǎng)上的tidyr代碼頭幾行為什么通常使用的是df %>% filter() %>% ...,而不是filter(df, ...)符相?如果使用管道符,就可以感受到最初的df只是一個輸入的對象啊终,而后續(xù)則是對數(shù)據(jù)框內(nèi)的元素進(jìn)行花式操作。如果這樣理解的話就會發(fā)現(xiàn)tidyr代碼的優(yōu)雅和易讀了趟脂。


參考

http://www.360doc.com/content/21/0805/12/73394596_989613319.shtml
https://bookdown.org/rdpeng/rprogdatascience/managing-data-frames-with-the-dplyr-package.html#dplyr-grammar
https://blog.csdn.net/m0_52406014/article/details/123823476

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末例衍,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子镇眷,更是在濱河造成了極大的恐慌翎嫡,老刑警劉巖永乌,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異圈驼,居然都是意外死亡望几,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進(jìn)店門橄抹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人玉锌,你說我怎么就攤上這事疟羹≈魇兀” “怎么了榄融?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵愧杯,是天一觀的道長涎才。 經(jīng)常有香客問我民效,道長涛救,這世上最難降的妖魔是什么业扒? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮程储,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘摊灭。我一直安慰自己败徊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布煤杀。 她就那樣靜靜地躺著,像睡著了一般沈自。 火紅的嫁衣襯著肌膚如雪辜妓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天籍滴,我揣著相機(jī)與錄音,去河邊找鬼捶索。 笑死,一個胖子當(dāng)著我的面吹牛腥例,可吹牛的內(nèi)容都是我干的酝润。 我是一名探鬼主播燎竖,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼构回,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纤掸?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤借跪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歇由,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡沦泌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年辛掠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片公浪。...
    茶點(diǎn)故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出镜撩,到底是詐尸還是另有隱情,我是刑警寧澤袁梗,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布遮怜,位于F島的核電站淋袖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏即碗。R本人自食惡果不足惜陌凳,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望合敦。 院中可真熱鬧初橘,春花似錦、人聲如沸保檐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盐肃。三九已至,卻和暖如春砸王,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谦铃。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工驹闰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瘪菌,地道東北人。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓师妙,卻偏偏與公主長得像屹培,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子褪秀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評論 2 345

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