有没有一种方法根据条件将相关的变量合并为一个变量?

6
假设我有多个变量来衡量物质滥用,即a1用于酒精使用a2用于大麻a3用于可卡因。我想生成变量afin,如果三个中的任何一个是“是”,则表示从事物质滥用。
有没有一种方法可以缩短代码,以便我不需要指定使用多个ifelse语句,如下所示?试图找到最佳方法,因为我有超过10个要合并成一个,并写ifelse可能不理想。
# Anymatch
library(tidyverse)

set.seed(2021)

mydata <- tibble(
  a1 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  a2 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  a3 = factor(round(runif(20, 1, 3)),
              labels = c("Yes", "No", "N/A")),
  b1 = round(rnorm(20, 10, 2)))
mydata

mydata <- mydata %>%
  mutate(afin = ifelse(a1 == "Yes"|a2=="Yes"|a3=="Yes", "Yes", "No"))

4个回答

4
我们也可以不使用 ifelse。只需将逻辑列转换为数字索引,并传递一个 vector 来替换值。
library(dplyr)
mydata %>%
     mutate(afin = c("no", "yes")[1 + (rowSums(select(cur_data(), 
        starts_with('a')) == 'Yes') > 0)])

-输出

# A tibble: 20 x 5
   a1    a2    a3       b1 afin 
   <fct> <fct> <fct> <dbl> <chr>
 1 No    Yes   Yes       6 yes  
 2 N/A   N/A   N/A       7 no   
 3 No    No    No       12 no   
 4 No    No    N/A       7 no   
 5 No    No    Yes       9 yes  
 6 No    N/A   N/A       7 no   
 7 No    N/A   N/A       7 no   
 8 No    N/A   Yes       7 yes  
 9 N/A   N/A   Yes      10 yes  
10 N/A   N/A   N/A      11 no   
11 Yes   Yes   No       10 yes  
12 N/A   N/A   No       14 no   
13 No    N/A   Yes       9 yes  
14 No    N/A   No       14 no   
15 N/A   No    No       10 no   
16 No    Yes   Yes       8 yes  
17 No    N/A   No       13 no   
18 N/A   Yes   No        9 yes  
19 N/A   N/A   N/A      11 no   
20 No    No    N/A      11 no   

或者使用 c_across
mydata %>% 
   rowwise %>%
   mutate(afin = c("no", "yes")[1+ 
          any(c_across(starts_with('a')) == "Yes")]) %>% 
   ungroup

1
亲爱的朋友,已点赞。我第一次看到这种策略。直到现在,我一直在努力使用 starts_withends_withcur_data()。所以我们必须使用 select(cur_data(), starts_with('something') ) 吗?因为 cur_data()[starts_with('something')] 的效果不是预期的吗?太棒了! - AnilGoyal
1
@AnilGoyal 谢谢。根据它们的文档,“选择助手可用于诸如dplyr::select()或tidyr::pivot_longer()”之类的函数中。因此,可能在那些tidyverse函数之外无法正常工作。 - akrun

4
我们也可以使用以下解决方案:
library(dplyr)
library(purrr)

mydata %>% 
  mutate(afin = pmap_chr(mydata %>% select(where(is.factor)), 
                         ~ {if(any(c(...) == "Yes")) "Yes" else "No"}))


# A tibble: 20 x 5
   a1    a2    a3       b1 afin 
   <fct> <fct> <fct> <dbl> <chr>
 1 No    Yes   Yes       6 Yes  
 2 N/A   N/A   N/A       7 No   
 3 No    No    No       12 No   
 4 No    No    N/A       7 No   
 5 No    No    Yes       9 Yes  
 6 No    N/A   N/A       7 No   
 7 No    N/A   N/A       7 No   
 8 No    N/A   Yes       7 Yes  
 9 N/A   N/A   Yes      10 Yes  
10 N/A   N/A   N/A      11 No   
11 Yes   Yes   No       10 Yes  
12 N/A   N/A   No       14 No   
13 No    N/A   Yes       9 Yes  
14 No    N/A   No       14 No   
15 N/A   No    No       10 No   
16 No    Yes   Yes       8 Yes  
17 No    N/A   No       13 No   
18 N/A   Yes   No        9 Yes  
19 N/A   N/A   N/A      11 No   
20 No    No    N/A      11 No 

3

你可以使用rowSums函数 -

library(dplyr)

mydata %>% 
   mutate(afin = ifelse(rowSums(select(., a1:a3) == 'Yes') > 0, 'yes', 'no'))

#   a1    a2    a3       b1 afin 
#   <fct> <fct> <fct> <dbl> <chr>
# 1 No    Yes   Yes       6 yes  
# 2 N/A   N/A   N/A       7 no   
# 3 No    No    No       12 no   
# 4 No    No    N/A       7 no   
# 5 No    No    Yes       9 yes  
# 6 No    N/A   N/A       7 no   
# 7 No    N/A   N/A       7 no   
# 8 No    N/A   Yes       7 yes  
# 9 N/A   N/A   Yes      10 yes  
#10 N/A   N/A   N/A      11 no   
#11 Yes   Yes   No       10 yes  
#12 N/A   N/A   No       14 no   
#13 No    N/A   Yes       9 yes  
#14 No    N/A   No       14 no   
#15 N/A   No    No       10 no   
#16 No    Yes   Yes       8 yes  
#17 No    N/A   No       13 no   
#18 N/A   Yes   No        9 yes  
#19 N/A   N/A   N/A      11 no   
#20 No    No    N/A      11 no   

3

data.table选项

setDT(mydata)[, afin := c("no", "yes")[1 + (rowSums(.SD == "Yes") > 0)], .SDcols = patterns("a")]

提供

     a1  a2  a3 b1 afin
 1:  No Yes Yes  6  yes
 2: N/A N/A N/A  7   no
 3:  No  No  No 12   no
 4:  No  No N/A  7   no
 5:  No  No Yes  9  yes
 6:  No N/A N/A  7   no
 7:  No N/A N/A  7   no
 8:  No N/A Yes  7  yes
 9: N/A N/A Yes 10  yes
10: N/A N/A N/A 11   no
11: Yes Yes  No 10  yes
12: N/A N/A  No 14   no
13:  No N/A Yes  9  yes
14:  No N/A  No 14   no
15: N/A  No  No 10   no
16:  No Yes Yes  8  yes
17:  No N/A  No 13   no
18: N/A Yes  No  9  yes
19: N/A N/A N/A 11   no
20:  No  No N/A 11   no

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接