以使用mutate、cross和case_when为条件连接一列中的列名
我想要:
- 使用
across和case_when检查列 A1-A3 == 1 - 连接 A1-A3 == 1 和
- 使用连接的列名改变新列
我的数据框:
df <- tribble(
~ID, ~A1, ~A2, ~A3,
1, 0, 1, 1,
2, 0, 1, 1,
3, 1, 1, 1,
4, 1, 0, 1,
5, 0, 1, 0)
期望输出:
# A tibble: 5 x 5
ID A1 A2 A3 New_Col
<dbl> <dbl> <dbl> <dbl> <chr>
1 1 0 1 1 A2 A3
2 2 0 1 1 A2 A3
3 3 1 1 1 A1 A2 A3
4 4 1 0 1 A1 A3
5 5 0 1 0 A2
到目前为止,我已经尝试过:
df %>%
rowwise() %>%
mutate(New_Col = across(A1:A3, ~ case_when(. == 1 ~ paste0("colnames(.)", collapse = " "))))
不工作输出:
ID A1 A2 A3 New_Col$A1 $A2 $A3
<dbl> <dbl> <dbl> <dbl> <chr> <chr> <chr>
1 1 0 1 1 NA colnames(.) colnames(.)
2 2 0 1 1 NA colnames(.) colnames(.)
3 3 1 1 1 colnames(.) colnames(.) colnames(.)
4 4 1 0 1 colnames(.) NA colnames(.)
5 5 0 1 0 NA colnames(.) NA
我想学习的内容:
- 是否可以用于
across检查多列的条件 - 如果是,如何查看 ~ of 之后的部分
case_when以获取特定的列名 - 我怎样才能使用后得到只有一列
mutate,across并case_when与喜欢这里不是3。
我以为我已经能够掌握这项任务,但不知何故我失去了它......
回答
across与case_when您一起使用可以 -
library(dplyr)
library(tidyr)
df %>%
mutate(across(A1:A3, ~case_when(. == 1 ~ cur_column()), .names = 'new_{col}')) %>%
unite(New_Col, starts_with('new'), na.rm = TRUE, sep = ' ')
# ID A1 A2 A3 New_Col
# <dbl> <dbl> <dbl> <dbl> <chr>
#1 1 0 1 1 A2 A3
#2 2 0 1 1 A2 A3
#3 3 1 1 1 A1 A2 A3
#4 4 1 0 1 A1 A3
#5 5 0 1 0 A2
across创建3名为新列new_A1,new_A2并new_A3与列名,如果该值是1或NA以其它方式。使用unite我们将 3 列合并为一列New_col。
此外,我们可以使用rowwise同c_across-
df %>%
rowwise() %>%
mutate(New_Col = paste0(names(.[-1])[c_across(A1:A3) == 1], collapse = ' '))
回答
没有rowwise/across你也可以使用cur_data()
df %>% group_by(ID) %>%
mutate(new_col = paste0(names(df[-1])[as.logical(cur_data())], collapse = ' '))
# A tibble: 5 x 5
# Groups: ID [5]
ID A1 A2 A3 new_col
<dbl> <dbl> <dbl> <dbl> <chr>
1 1 0 1 1 A2 A3
2 2 0 1 1 A2 A3
3 3 1 1 1 A1 A2 A3
4 4 1 0 1 A1 A3
5 5 0 1 0 A2
a.而不是dfinside mutate 也可以
df %>% group_by(ID) %>%
mutate(new_col = paste0(names(.[-1])[as.logical(cur_data())], collapse = ' '))