错误:“mutate()”输入“coding”有问题 x 没有适用于“选择”的方法应用于“字符”类的对象

问题描述

我已经无能为力了。我试图在我的管道中做一个相当简单的变异,但对于一个特定的例子,R 只是拒绝工作。抱歉,我无法提供可重现的示例(原因如下所述)。

这是我的完整管道:

new <- old %>%
  left_join(.,lookup,by = "id") %>%
  mutate(sum_0.95   = apply(across(starts_with("pred")),1,function(x) {sum(x >= 0.95 & x < 1)}),sum_le_0.5 = apply(across(starts_with("pred")),function(x) {sum(x <= 0.5 & x > 0)}),coding = case_when(pred_QC4A_code_10 == 0 | pred_QC4A_code_10 == 1 ~ "ABC",sum_0.95 > 0 & (sum_0.95 + sum_le_0.5 == (lookup %>% select(starts_with("pred")) %>% names() %>% length())) ~ "DEF",TRUE ~ "XYZ")) %>%
  select(-starts_with("pred"),-sum_0.95,-sum_le_0.5)

这会给出一条错误消息(由于 case_when 中的 lookup %>% select(starts_with("pred")) %>% names() %>% length() 部分)。

# Error: Problem with `mutate()` input `coding`.
# x no applicable method for 'select' applied to an object of class "character"

问题是:

  • 完全相同的结构/代码示例适用于不同的数据集
  • 如果我只用它的数字结果 (29) 替换有问题的部分,它就可以工作
  • 如果我用相同结构的不同数据集替换 lookup,它会起作用
  • 如果我执行 test <- lookup 并通过管道中的测试替换查找,它会起作用
  • 如果我执行test <- dput(lookup),与上面相同,它会起作用

identical(test,lookup) 的检查也返回 TRUE

这也是我不能为你提供一个工作示例的原因。因为无论我做什么(例如 dput),错误都不再重现。

这里至少是 str(lookup) 结果

'data.frame':   5625 obs. of  30 variables:
 $ id                 : chr  "A" "B" "C" "D" ...
 $ pred_QC4A_code_10  : num  1 0 0 1 1 1 1 0 1 1 ...
 $ pred_QC4A_code_11  : num  0 0 0 0 0 0 0 0 0 1 ...
 $ pred_QC4A_code_12  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_13  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_14  : num  0 0 0 0 0 0 0 1 0 0 ...
 $ pred_QC4A_code_15  : num  0 0 1 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_16  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_17  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_20  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_21  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_22  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_23  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_30  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_31  : num  0 1 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_32  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_33  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_34  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_40  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_41  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_42  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_43  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_44  : num  0 0 0 0 1 0 0 0 0 0 ...
 $ pred_QC4A_code_80  : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_995 : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_996 : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_997 : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_998 : num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_9991: num  0 0 0 0 0 0 0 0 0 0 ...
 $ pred_QC4A_code_9992: num  0 0 0 0 0 0 0 0 0 0 ...

我认为它确实与 select 命令有关,但不知道发生了什么。


更新:解决了问题。问题是在我的 new 数据框中,我还有一个名为 lookup 的列,因此 case_when 正在访问此列而不是外部数据集,这当然不起作用。

解决方法

最好在外面创建一个对象,因为它是固定的

v1 <- lookup %>%
        select(starts_with("pred")) %>% 
        names() %>% 
        length()

然后,我们可以简化它

...
 coding = case_when(pred_QC4A_code_10 == 0 | pred_QC4A_code_10 == 1 ~ "ABC",sum_0.95 > 0 & ((sum_0.95 + sum_le_0.5) == (v1))) ~ "DEF",TRUE ~ "XYZ")) 

OP 提到数据集中有一个名为“lookup”的列。所以,如果我们需要使用全局环境中的对象,而不是列,转义 (!!)

 new <- old %>%
  left_join(.,lookup,by = "id") %>%
  mutate(sum_0.95   = apply(across(starts_with("pred")),1,function(x) {sum(x >= 0.95 & x < 1)}),sum_le_0.5 = apply(across(starts_with("pred")),function(x) {sum(x <= 0.5 & x > 0)}),coding = case_when(pred_QC4A_code_10 == 0 | pred_QC4A_code_10 == 1 ~ "ABC",sum_0.95 > 0 & (sum_0.95 + sum_le_0.5 == (!!lookup %>% select(starts_with("pred")) %>% names() %>% length())) ~ "DEF",TRUE ~ "XYZ")) %>%
  select(-starts_with("pred"),-sum_0.95,-sum_le_0.5)