R语言:映射数据框列表时deparse()与paste()不符合预期
问题分析与解决:映射列表数据框时deparse()无法获取元素名称
问题描述
有一个命名列表list1,包含多个数据框,所有数据框列名均为barcode和count。编写了自定义函数barcode_frequency,用于计算频率并重命名列(添加数据框名称后缀):
list1 <- list(ute1, dec1, dec2, dec3, dec4, dec5, dec6, dec7, dec8, pla1, pla2, pla3, pla4, pla5, pla6, pla7, pla8) names <- c("ute1", "dec1", "dec2", "dec3", "dec4", "dec5", "dec6", "dec7", "dec8", "pla1", "pla2", "pla3", "pla4", "pla5", "pla6", "pla7", "pla8") names(list1) <- names barcode_frequency <- function(x) { df_name <- deparse(substitute(x)) totalumis <- sum(x$count) x$freq <- ((x$count)/totalumis) colnames(x) <- paste(colnames(x), df_name, sep = "_") print(x) }
单独调用函数(如barcode_frequency(ute1))时,列名能正确添加数据框名称后缀;但用map(list1, barcode_frequency)映射整个列表时,deparse()返回的是.x[[i]],导致列名变为barcode_.x[[i]],不符合预期。
原因解释
deparse(substitute(x))的作用是获取调用函数时传入的参数表达式:
- 单独调用时,传入的是变量名(比如
ute1),所以substitute(x)会捕获这个变量名,deparse后得到对应的字符串。 - 使用
map时,map内部是循环遍历列表元素,传给barcode_frequency的参数是.x[[i]](purrr内部的迭代变量),因此substitute(x)捕获的是这个迭代表达式,deparse后自然得到.x[[i]],而非列表元素的名称。
解决方案
不需要依赖deparse(substitute(x)),直接传递列表元素的名称给函数即可,推荐两种方法:
方法1:使用map2同时迭代元素和名称
map2可以同时处理两个长度相同的向量/列表,这里用它同时传递数据框和对应的名称:
barcode_frequency <- function(x, df_name) { totalumis <- sum(x$count) x$freq <- x$count / totalumis colnames(x) <- paste(colnames(x), df_name, sep = "_") x # 移除print,让函数返回处理后的数据集 } list2 <- map2(list1, names(list1), barcode_frequency)
方法2:使用imap(purrr语法糖)
imap是map2的简化版,默认会把列表元素的名称作为第二个参数传入函数,无需手动指定names(list1):
barcode_frequency <- function(x, df_name) { totalumis <- sum(x$count) x$freq <- x$count / totalumis colnames(x) <- paste(colnames(x), df_name, sep = "_") x } list2 <- imap(list1, barcode_frequency)
两种方法都能让函数正确获取列表元素的名称,生成符合预期的列名(如barcode_ute1、count_dec1等)。
内容的提问来源于stack exchange,提问作者fitz_meyer
相关产品推荐
相关产品推荐

