获取更好阅读体验:R语言-Reduce函数 让你的代码优美且强大。
一、摘要
上篇推文介绍了如何快速对多个变量取交集:R语言-快速对多个变量取交集,最终用到了Reduce
函数。
本文将专门介绍Reduce
函数地绝妙之处,让你的代码简短而强大。
在R语言数据处理的过程中,我们经常需要对不同类型的数据进行聚合、累积或归约操作。Reduce
函数是R语言中一个强大的工具,能够将一个序列的元素逐步减少为单个结果。本文将带您深入探索Reduce
函数的技巧与窍门,助您在处理数字、字符、数据框、列表等不同类型的数据时事半功倍。
二、参数解释
在使用Reduce()函数时,我们需要了解以下关键参数的含义:
f
:这是一个二元函数,用于指定如何将序列中的元素逐步减少为单个结果。函数f
接受两个参数,第一个参数是前一个累积值,第二个参数是下一个元素。x
:这是一个序列,可以是向量、列表、矩阵、数据框或其他可迭代的数据结构。Reduce()函数将按顺序处理序列中的元素,并将每个元素传递给函数f
进行累积计算。init
(可选):这是Reduce()函数的初始累积值。如果未提供init
参数,则默认使用序列中的第一个元素作为初始累积值。right
(可选,默认为FALSE
):这是一个逻辑值,用于指定累积计算的方向。如果right
为FALSE
(默认值),则Reduce()函数从左到右按顺序处理序列中的元素。accumulate
(可选,默认为FALSE
):这也是一个逻辑值,用于指定是否返回中间累积结果的向量。如果accumulate
为FALSE
(默认值),则Reduce()函数仅返回最终的累积结果。
三、使用示例
下面展示Reduce
函数在实际数据处理中的用法,大家举一反三,观察其使用场景以灵活运用。
1. 多个变量取交集
就是上个推文介绍的:
# 生成10个数字集合
for(i in 1:10){
var_name = paste0("var", i)
set.seed(i)
nums = sample(1:100, 80)
assign(var_name, nums)
}
Reduce(intersect, lapply(paste0("var", 1:10), get))
# [1] 87 59 21 84 42 24 18 76 16
2. 多个数据框合并
在for
循环中,经常会遇到每个循环生成一个数据框,你可以先把每个循环的数据框保存在列表里,再使用Reduce
进行合并。
resL = list()
for(i in 1:5){
from = 1 + 10 * i
to = from + 2
resL[[i]] = iris[from:to, ]
}
resT = Reduce(rbind, resL)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
# 11 5.4 3.7 1.5 0.2 setosa
# 12 4.8 3.4 1.6 0.2 setosa
# 13 4.8 3.0 1.4 0.1 setosa
# 21 5.4 3.4 1.7 0.2 setosa
# 22 5.1 3.7 1.5 0.4 setosa
# 23 4.6 3.6 1.0 0.2 setosa
# 31 4.8 3.1 1.6 0.2 setosa
# 32 5.4 3.4 1.5 0.4 setosa
# 33 5.2 4.1 1.5 0.1 setosa
# 41 5.0 3.5 1.3 0.3 setosa
# 42 4.5 2.3 1.3 0.3 setosa
# 43 4.4 3.2 1.3 0.2 setosa
# 51 7.0 3.2 4.7 1.4 versicolor
# 52 6.4 3.2 4.5 1.5 versicolor
# 53 6.9 3.1 4.9 1.5 versicolor
3. 合并单细胞样本
# https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE146170
# 获取每个样本的细胞注释文件路径
anno_file = lf("rf", "00_raw/anno")
# lapply批量读取, 并使用Reduce合并
anno_tb = Reduce(rbind, lapply(anno_file, function(x) data.table::fread(x, data.table = FALSE)))
# 获取每个样本的表达矩阵文件路径
umi_file = lf("rf", "00_raw/UMI")
# lapply批量读取
umi_list = lapply(umi_file, function(x) data.table::fread(x, data.table = FALSE))
# 使用Reduce合并
umi_tb = Reduce(function(df1, df2) merge(df1, df2, by = "gene_name", all = TRUE), umi_list)
# 首列转为行名
umi_tb = col2rownames(umi_tb, remove = TRUE)
# 构建Seurat对象
loadp(Seurat)
obj = CreateSeuratObject(counts = umi_tb, meta.data = anno_tb)
obj
可以看到,结合lappy家族,代码更为简洁高效,因为后者输出的结果正可以作为前者的输入。
4. 处理单个数据框
- 直接合并每个元素
tb = cars[1:5, ]
Reduce(c, tb)
# [1] 4 4 7 7 8 2 10 4 22 16
- 其实
unlist
也可以,没想到吧,数据框其实也是列表,一种特殊的列表(使用typeof
函数可以看出)
unlist(tb)
# speed1 speed2 speed3 speed4 speed5 dist1 dist2 dist3 dist4 dist5
# 4 4 7 7 8 2 10 4 22 1
5. 累加
- 如何使用R语言计算1到100的和?
Reduce(`+`, 1:100)
# [1] 5050
例子是举不完的,大家要灵活使用。
Reduce
函数是不是很优美和强大!
学习更多生信技巧,持续关注【生信摆渡】
!