提问人:TarJae 提问时间:5/30/2021 更新时间:5/31/2021 访问量:1987
在一列中连接列名,条件是使用 mutate、across 和 case_when
Concatenate column names in one column conditional on using mutate, across and case_when
问:
我想:
- 使用并检查列 A1-A3 == 1
across
case_when
- 连接列的列名,其中 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
- 如果是,那么 ~ 之后的部分看起来如何,以获取特定的 colnames
case_when
- 使用后我怎么能只得到一列,而不是像这里这样的 3 列。
mutate
across
case_when
我以为我已经能够掌握这项任务,但不知何故我失去了它......
答:
11赞
Ronak Shah
5/30/2021
#1
与你一起使用可以做 -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 个名为 的新列,如果值为 1 或其他,则使用列名称。使用我们将 3 列合并为一列。new_A1
new_A2
new_A3
NA
unite
New_col
我们也可以与rowwise
c_across
-
df %>%
rowwise() %>%
mutate(New_Col = paste0(names(.[-1])[c_across(A1:A3) == 1], collapse = ' '))
评论
0赞
AnilGoyal
5/30/2021
Ronak,而不是 names(),我们可以在这里直接使用cur_column吗?
0赞
Ronak Shah
5/30/2021
你的意思是在或对?我不认为我们可以这样做,因为只能在内部使用。rowwise
group_by
ID
cur_column
across
0赞
AnilGoyal
5/30/2021
是的,它只返回此错误。谢谢你解释:)
7赞
AnilGoyal
5/30/2021
#2
没有/您也可以使用相同的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
一个而不是内部的突变也可以.
df
df %>% group_by(ID) %>%
mutate(new_col = paste0(names(.[-1])[as.logical(cur_data())], collapse = ' '))
评论
1赞
Karthik S
5/30/2021
很棒的 Anil ji 和 Ronak,有一个查询,这是每个组,即使每个组有超过 1 行,它也能工作吗?因为我尝试并期望 DF 为 和 但得到这个错误:.和 之间有什么区别cur_data
as.logical(df[-1])
TRUE
FALSE
Error: 'list' object cannot be coerced to type 'logical'
cur_data
cur_group
1赞
AnilGoyal
5/30/2021
嗨,@KarthikS,你可以叫我阿尼尔,请看这里的一些解释。 返回当前数据(当然是分组的)并表示组键。因此,将在此处返回二进制值并返回 ids。希望这是清楚的cur_data
cur_group
cur_data
cur_group
3赞
tmfmnk
5/30/2021
#3
一个选项也可能是:purrr
df %>%
mutate(New_Col = pmap_chr(across(-ID),
~ paste(names(c(...))[which(c(...) == 1)], collapse = " ")))
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
4赞
akrun
5/31/2021
#4
用base R
df$New_Col <- apply(df[-1], 1, \(x) paste(names(x)[as.logical(x)], collapse=' '))
df$New_Col
#[1] "A2 A3" "A2 A3" "A1 A2 A3" "A1 A3" "A2"
或者使用tidyverse
library(dplyr)
library(purrr)
library(stringr)
df %>%
mutate(New_Col = across(A1:A3, ~ c('', cur_column())[. + 1] ) %>%
invoke(str_c, .))
评论