如何用dplyr筛选列名含连字符的R data.frame?
问题
我有一个单列多行的模型输出矩阵,列名根据输入条件生成,格式为St1-St2,列值为0、1或-1。想要筛选出值不等于0的行,尝试用rlang注入的方式编写dplyr筛选代码,但运行时出现「找不到对象'St1-St2'」的错误,请问如何处理列名中的连字符问题?
示例代码
# 矩阵示例 mat1.data <- c(1,0,0,0,1,-1,-1,0,1) m_rownames <- c("g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8", "g9") mat1 <- matrix(mat1.data, nrow=9,ncol=1,byrow=TRUE) colnames(mat1) <- "St1-St2" rownames(mat1) <- m_rownames mat1 # 获取列名 m_column <- colnames(mat1) # 尝试用rlang注入进行筛选 mat2 <- data.frame(mat1) %>% dplyr::filter(!!as.symbol(m_column) != 0) %>% rownames_to_column()
错误信息
#> Error in `dplyr::filter()`: #> ! Problem while computing `..1 = `St1-St2` != 0`. #> Caused by error in `mask$eval_all_filter()`: #> ! object 'St1-St2' not found #> Run `rlang::last_error()` to see where the error occurred.
解决方案
错误根源是as.symbol()会把带连字符的列名解析成St1 - St2(即两个对象相减的表达式),而非完整的列名。以下是几种可行的解决方法:
方法1:使用.data代词(推荐)
dplyr提供的.data代词可直接引用动态列名,代码简洁且不易出错:
mat2 <- data.frame(mat1) %>% dplyr::filter(.data[[m_column]] != 0) %>% rownames_to_column()
方法2:用rlang::parse_expr()包裹反引号
若坚持使用rlang注入,可将列名用反引号包裹后解析为表达式,让R识别为完整列名:
mat2 <- data.frame(mat1) %>% dplyr::filter(!!rlang::parse_expr(paste0("`", m_column, "`")) != 0) %>% rownames_to_column()
方法3:使用across()函数
利用across()指定目标列完成筛选,同样支持带特殊字符的列名:
mat2 <- data.frame(mat1) %>% dplyr::filter(across(all_of(m_column), ~ .x != 0)) %>% rownames_to_column()
内容的提问来源于stack exchange,提问作者Alexandr Romanko
相关产品推荐
相关产品推荐

