【问题标题】:Using dplyr and mutate to counting the number of columns that meet a criterion使用 dplyr 和 mutate 计算满足条件的列数
【发布时间】:2021-03-19 11:33:17
【问题描述】:

最小示例:一个包含 4 列的小型数据框和一个包含我要创建的新列名称的变量。如果对超过一定数量的问题的回答超过阈值,则新列为 TRUE,否则为 FALSE

df1 <- data.frame(ID = LETTERS[1:5],
                  Q1 = sample(0:10, 5, replace=T),
                  Q2 = sample(0:10, 5, replace=T)
                  Q3 = sample(0:10, 5, replace=T)
                  Q4 = sample(0:10, 5, replace=T)
)

这给了我对各种问题的回答的数据框:

> df1
  ID Q1 Q2 Q3 Q4
1  A  2  4  5  0
2  B  9  6  6  3
3  C  5  5  3  2
4  D  0  5  3 10
5  E  7  5  6  7

我还定义了以下常量:

QUESTIONS  <- c("Q1”,  “Q2”,  “Q3”,  “Q4")
MY_NEW_COL <- "New_Col"
THESHOLD1  <- 5
THESHOLD2  <- 2

我想添加一个名为 New_Col 的新列,如果超过 THRESHOLD2 列的值超过 THRESHOLD1,则该列为 TRUE。我可以让它以一种笨拙但显而易见的方式工作:

df1 %>%
    mutate(!!MY_NEW_COL := ( (Q1 > THREHOLD1) + (Q2> THREHOLD1) +   
                             (Q3 > THREHOLD1) + (Q4> THREHOLD1)  ) > THRESHOLD2)

这给出了正确的答案:

  ID Q1 Q2 Q3 Q4 New_Col
1  A  2  4  5  0   FALSE
2  B  9  6  6  3    TRUE
3  C  5  5  3  2   FALSE
4  D  0  5  3 10   FALSE
5  E  7  5  6  7    TRUE

但我想把这个系统化一下,因为总共有 17 个问题。我在下面显示的代码给出了错误的答案

df1 %>%
    mutate(!!MY_NEW_COL := sum(all_of(QUESTIONS) > THRESHOLD1)) > THRESHOLD2)

  ID Q1 Q2 Q3 Q4 New_Col
1  A  2  4  5  0    TRUE
2  B  9  6  6  3    TRUE
3  C  5  5  3  2    TRUE
4  D  0  5  3 10    TRUE
5  E  7  5  6  7    TRUE

我在做什么,我该如何解决这个问题?

在此先感谢

托马斯·飞利浦

【问题讨论】:

  • 我一直在查看您的代码,在发布答案之前,我想在这里解决您对QUESTIONS 的定义的问题。你的引号破坏了你的代码,你应该使用“或',没有其他东西来定义字符串。QUESTIONS &lt;- c("Q1", "Q2", "Q3", "Q4")
  • 我无法运行您的代码df1 %&gt;% mutate(!!MY_NEW_COL := ( (Q1 &gt; THREHOLD1) + (Q2&gt; THREHOLD1) + (Q3 &gt; THREHOLD1) + (Q4&gt; THREHOLD1) ) &gt; THRESHOLD2)。它报告错误“错误:mutate() 输入 New_Col 出现问题。未找到 x 对象 'THREHOLD1'”。
  • OP 的帖子中有不少拼写错误。这些都应该纠正。他定义了THESHOLD1,但调用了THREHOLD1——这就是为什么你的代码不起作用@Peace Wang
  • 为错误道歉
  • 这个问题怎么还没有选择的答案....

标签: r dplyr


【解决方案1】:

由于您没有提供seed,因此无法准确重现您的结果。您的问题的解决方案是使用across()rowSums(),这样,

df1 %>%
    mutate(!!MY_NEW_COL := rowSums(across(QUESTIONS) > THESHOLD1) > THESHOLD2) 

它给出了输出,

  ID Q1 Q2 Q3 Q4 New_Col
1  A  7  9  1  1   FALSE
2  B  3  9  9  7    TRUE
3  C  4  0  6  6   FALSE
4  D  5  1  6 10   FALSE
5  E  6  5  5  1   FALSE

【讨论】:

  • 但是,使用您当前的代码,您可能无法立即使其工作。您必须对代码进行排序和更正才能正常工作。
  • 它有效,我通过写mutate(!!MY_NEW_COL := rowSums(across(all_of(QUESTIONS)) &gt; THRESHOLD1) &gt; THRESHOLD2) 修复了 R 警告消息。为拼写错误道歉。
  • 别担心! :-) 我希望你能找到合适的解决方案。
  • 如果您找到了答案,请选择一个,以便我们关闭它。如果没有,请更新您的帖子。
【解决方案2】:

我们也可以

library(dplyr)
library(purrr)
library(magrittr)
 df1 %>% 
   mutate(!! MY_NEW_COL := map(select(cur_data(), starts_with("Q")),
        ~ .x > THESHOLD1) %>%
             reduce(`+`) %>% 
             is_greater_than(THESHOLD2) )

【讨论】:

    【解决方案3】:

    不知道下面的输出是不是你心目中的,但我先检查了是否所有Qs都大于阈值1,如果是,则其总和是否大于阈值2:

    library(dplyr)
    
    f1 <- function(x, threshold1 = 2, threshold2 = 5) {
      df1 <- df1 %>%
        group_by(ID) %>%
        mutate(threshold_1 = if_all(, ~ .x > 2, TRUE),
               sum_Qs = sum(Q1:Q4),
               threshold_2 = if_else(sum_Qs > threshold2 & threshold_1 == TRUE, 
                                     TRUE, FALSE))
      df1
    }
    
    f1(df1, 2, 5)
    
    # A tibble: 5 x 8
    # Groups:   ID [5]
      ID       Q1    Q2    Q3    Q4 threshold_1 sum_Qs threshold_2
      <chr> <int> <int> <int> <int> <lgl>        <int> <lgl>      
    1 A         8     0     1    10 FALSE           27 FALSE      
    2 B         2     3     2     8 FALSE           35 FALSE      
    3 C         1     8     4     3 FALSE            6 FALSE      
    4 D         9     3     3     9 TRUE             9 TRUE       
    5 E         1     3     0     1 FALSE            1 FALSE 
    

    【讨论】:

      猜你喜欢
      • 2021-08-13
      • 2019-04-30
      • 1970-01-01
      • 2013-10-14
      • 2020-05-04
      • 1970-01-01
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多