在R语言中如何结合map2使用unite函数?
我尝试在管道链里用map2调用unite(),合并两组各4列的数据,生成2个合并列并绑定到当前tibble,但代码运行出错。测试代码如下:
library(tidyverse) df <- tibble(a_col1=sample(letters,10), a_col2=sample(letters,10), b_col1=sample(letters,10), b_col2=sample(letters,10)) %>% bind_cols(., map2(.x = c("merged_a", "merged_b"), .y=c("a_col", "b_col"), ~ unite(select(.data, starts_with(.y)), col=!!.x, sep = ",", na.rm = TRUE, remove = TRUE)))
运行后抛出错误:
Error in
map2():
ℹ In index: 1.
Caused by error inUseMethod():
! no applicable method for 'select' applied to an object of class "rlang_fake_data_pronoun"
Runrlang::last_trace()to see where the error occurred.
管道外执行相同逻辑是正常的,推测问题出在将当前tibble传递到map2内部的unite()函数中,尝试用大括号传递也没成功。
可运行代码(附解释)
后来找到能正常运行的代码:
library(tidyverse) df <- tibble(a_col1=sample(letters,10), a_col2=sample(letters,10), b_col1=sample(letters,10), b_col2=sample(letters,10)) %>% bind_cols(., map2(.x = c("merged_a", "merged_b"), .y=c("a_col", "b_col"), \(.x,.y) unite(select(., starts_with(.y)), col=!!.x, sep = ",", na.rm = TRUE, remove = TRUE)))
原因解释
原代码错误点:
在map2的公式语法(~)中,.data是rlang提供的假代词,它并非指向管道上游的tibble对象,而是用于在tidy eval中标记数据列的占位符,因此select(.data, ...)会报错——因为.data在这里不是实际的数据框,无法被select处理。修正后的逻辑:
改用R 4.1+支持的匿名函数语法\(.x,.y)后,函数内部的.直接引用了管道传递过来的tibble,select(., starts_with(.y))能正确筛选目标列,后续的unite自然可以正常执行。补充:如果坚持用公式语法,需要提前将上游数据赋值给变量(比如
df),然后在map2里明确引用:
df <- tibble(...) %>% bind_cols(., map2(.x = c("merged_a", "merged_b"), .y=c("a_col", "b_col"), ~ unite(select(df, starts_with(.y)), col=!!.x, sep = ",", na.rm = TRUE, remove = TRUE)))
但这种方式不够灵活,不如匿名函数直接用.引用管道数据方便。
内容的提问来源于stack exchange,提问作者user167591

