编程笔记6-dplyr常用语法

引言

一直以来都听闻tidy-r是使R语言起死回生的存在,尽管没有系统学习过,但已经在coding中潜移默化的使用了许多tidy语法,例如管道符%>%ggplot2等等。最近在处理bed文件时遇到了很多base-r解决起来非常复杂的问题,网上一查都是用dplyr包解决的。因此本文记录一下dplyr的常用语法,希望以后逐渐由base-r向tidy-r过渡。

tidyverse家族


dplyr函数特征

  1. 第一个参数是一个数据框。
  2. 随后的参数描述了如何处理第一个参数中指定的数据框,你可以直接引用数据框中的列,而无需使用 $ 运算符(只需使用列名)。
  3. 函数的返回结果是一个新的数据框
  4. 数据框必须经过正确格式化和注释才能发挥作用。尤其是数据必须整齐。简而言之,每一行应该有一个样本,每一列应该代表那个样本的特征。

筛选行:filter()

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

这里,flights是数据框,“month == 1, day == 1”是筛选条件,默认是且的关系,还可以用其他条件进行筛选:

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

排序行:arrange()

  • 按year, month, day的优先级排列数据框flights
arrange(flights, year, month, day)
  • 如果有多个列名,那么就先按前面的列名排,然后在此基础上排后面的列名
  • 默认按升序排(从小到大)
  • 用 desc() 降序排,如
arrange(flights, desc(arr_delay))
# 按arr_delay降序,对观测进行重排
  • 缺失值总是排在最后

筛选列:select()

  • 选择数据框flights中的year, month, day这几列
select(flights, year, month, day)
  • 选择“year”和“day”之间的所有列(包括“year”和“day”)
select(flights, year:day)
  • 选择不在“year”和“day”之间的所有列,记得带括号
select(flights, -(year:day))
  • 可以在 select () 函数中使用一些辅助函数,这些跟Excel中选择名称的规则类似
    starts_with("abc"):匹配 开头是“abc” 的名称。
    ends_with("xyz"):匹配 结尾是“xyz” 的名称。
    contains("ijk"):匹配 包含“ijk” 的名称。
    matches("(.)\\1"):选择匹配正则表达式的那些变量。这个正则表达式会匹配名称中有重复字符的变量。
    num_range("x", 1:3):匹配 x1、 x2 和 x3。

  • 把 time_hour 和 air_time 移到数据框的开头,其余按原来的顺序呈现

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

重命名列:rename()

  • 将变量tailnum重命名为tail_num
rename(flights, tail_num = tailnum)

添加新列:mutate()

  • 添加新列:gain 和 speed,并排在数据集的最后
mutate(flights,gain = arr_delay - dep_delay,speed = distance / air_time * 60) 
  • 新列一旦创建,就可立即使用。如在创建新列 gain_per_hour 的时候,用到了刚创建的新列 gain 和 hours
mutate(flights_sml,gain = arr_delay - dep_delay,hours = air_time / 60,gain_per_hour = gain / hours)
  • 如果只想保留新变量,可以使用 transmute() 函数,如下代码输出结果中只有3列:gain 、 hours 和 gain_per_hour
transmute(flights,gain = arr_delay - dep_delay,hours = air_time / 60,gain_per_hour = gain / hours)
  • 辅助运算符
    • 算术运算符:+、 -、 *、 /、 ^

    • 模运算符:%/%(求整) 和 %%(求余),可以拆分整数。

    • 对数函数:log()、 log2() 和 log10()。

    • 偏移函数:lead() 返回序列领先值、 lag() 返回序列滞后值。

    • 累加和滚动聚合:cumsum() 累加和、 cumprod() 累加积、commin() 累加最小值、 cummax() 累加最大值、cummean() 累加均值,这几个函数对于绘图非常重要

    • 逻辑比较:<、 <=、 >、 >= 和 !=

    • 排秩:最常用的是min_rank() ,升序排,输出结果是名次,如1 2 3 ... n。


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

  • 可以将数据框折叠成一行,如下代码输出为一个值,即所有航班的平均起飞延误时间
summarize(flights, delay = mean(dep_delay, na.rm = TRUE))
  • 与 group_by() 联用,即在分组基础上进行摘要统计。group_by() 和 summarize() 联用是 dplyr 包最常用的操作之一。
  • 如:将所有结果按method和benchmark分组,计算新分组的每组平均值,并用 n() 函数计数,返回当前分组的大小
> 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
  • 只使用均值、计数和求和是远远不够的, dplyr还提供了常见的摘要函数,如:

    1. 位置度量:median(x) 中位数
    2. 分散程度度量:sd(x) 标准误差、 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. 计数:n() 返回当前分组的大小, sum(!is.na(x)) 计算出非缺失值的数量, n_distinct(x) 计算出唯一值的数量,count()返回指定组合的计数
    6. 逻辑值的计数和比例:sum(x > 10) 找出 x 中 TRUE 的数量, mean(y == 0) 找出x 中 TRUE 的比例。
  • 用 ungroup() 函数取消分组,并回到未分组的数据继续操作


处理双表格

  • 左链接left_join():以左边的表的by变量为准合并,如果有数据缺失则显示NA。
  • 右链接right_join():以右边的表的by变量为准合并,如果有数据缺失则显示NA。
  • 内链接inner_join():返回两个表中的交集部分。
  • 外链接full_join():返回两表中的并集部分。

其他函数

  • add_count():给最后一列添加某列的counts数
  • distinct(col, .keep_all = T):只保留col不重复的行

实战

  • 计算单细胞矩阵的TPM
mm10_gene <- read.table('/mdshare/node10/xyx/projects/RNA-editing/reference/genome_bed/mm10/mm10_gene.bed')
mm10_gene %>% 
  as_tibble() %>%                                       # df转tibble
  transmute(gene_name = V6,                             # 新建一个tibble包含列gene_name
            length = V3 - V2) %>%                       # 包含列length为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()

总结

初次接触tidyr会感觉函数的形参比较随意,除了第一个参数必须是数据框本身,后续参数都没有严格要求,有的参数还是函数名(例如之前一直不太理解的ggplot2中的aes())。但实际上,这是因为tidyr的语法更多的是面向操作,而我之前使用的基于which()的筛选方法更多的是面向结果。想想网上的tidyr代码头几行为什么通常使用的是df %>% filter() %>% ...,而不是filter(df, ...)?如果使用管道符,就可以感受到最初的df只是一个输入的对象,而后续则是对数据框内的元素进行花式操作。如果这样理解的话就会发现tidyr代码的优雅和易读了。


参考

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容