为什么group_by在多个group和mutate上给我这个错误?

问题描述

所以我有这个数据框

               well day treatment stimulus animalid           name   value
1 03-Well-A1.fcs   0      MOCK     MOCK      G14 %prol. t-cells 0.00500
2 03-Well-A1.fcs   0      MOCK     MOCK      G14   %prol. tcrab 0.00370
3 03-Well-A1.fcs   0      MOCK     MOCK      G14 %prol. cd3+dn- 0.00067
4 03-Well-A1.fcs   0      MOCK     MOCK      G14      %prol. th 0.00100
5 03-Well-A1.fcs   0      MOCK     MOCK      G14    %prol. treg 0.00200
6 03-Well-A1.fcs   0      MOCK     MOCK      G14     %prol. ctl 0.00000
> str(test_valueadj)
'data.frame':   2160 obs. of  7 variables:
 $ well     : chr  "03-Well-A1.fcs" "03-Well-A1.fcs" "03-Well-A1.fcs" "03-Well-A1.fcs" ...
 $ day      : Factor w/ 5 levels "0","14","28",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ treatment: Factor w/ 4 levels "HP","LP","MLV",..: 4 4 4 4 4 4 4 4 4 4 ...
 $ stimulus : Factor w/ 4 levels "LP","HP","MOCK",..: 3 3 3 3 3 3 3 3 3 3 ...
 $ animalid : Factor w/ 24 levels "B14","B15","B16",..: 7 7 7 7 7 7 7 7 7 7 ...
 $ name     : Factor w/ 18 levels "% tcr-gd","%ctl",..: 7 8 5 9 10 6 3 4 18 17 ...
 $ value    : num  0.005 0.0037 0.00067 0.001 0.002 0 0.0013 0.00303 0.5 0 ...

然后我想将每个group_by(day,animalid,name)的值减去其他“处理”值(Hp,LP,MLV)的值

test_valueadj<-test_valueadj%>%
  group_by(animalid,day,name)%>%
  mutate(adjusted = (filter(treatment!="MOCK")$value)-(filter(treatment=="MOCK")$value))

然后我得到以下错误

Error: Problem with `mutate()` input `adjusted`.
x no applicable method for 'filter_' applied to an object of class "logical"
ℹ Input `adjusted` is `(filter(treatment == "HP")$value) - (filter(treatment == "MOCK")$value)`.
ℹ The error occurred in group 1: animalid = "B14",day = "0",name = "% tcr-gd".
Run `rlang::last_error()` to see where the error occurred.

我之前做过类似的操作,但效果很好,但无法查明是什么原因导致了此问题。

感谢您的帮助

解决方法

您对filter()的调用没有与其data.frame形式参数匹配的.data对象。

当您使用magrittr管道内插运算符%>%“管道连接”函数调用时,管道将基于管道RHS上的函数调用构造一个新的函数调用(即管道的rhs形式参数)。管道根据用户是否提供符号lhs来隐式或显式地将LHS表达式的值(.作为参数提供给RHS函数的形式运算符之一)。 rhs函数调用的整个参数。在用户提供的lhs调用参数中,它还会用.代替符号rhs的出现。

已通过管道传递到的任何dplyr动词中的.data的值(即管道函数的rhs自变量)将与{{1}的值匹配}管道函数的形式参数,只要用户未通过提供lhs的值作为命名参数来指定它。)您对函数.data的调用发生在内部 filter()的参数。它们不是函数调用mutate()的{​​{1}}参数,它们只是出现在rhs的{​​{1}}参数中。管道不会从作为管道正在修改的函数的参数提供的函数调用中递归构造新的函数调用。除非您通过指定.data的值在位置或名称上均应为符号%>%来明确提供它,否则管道将不会尝试将LHS对象作为参数提供给它们。

rhs是您要提供给%>%函数的参数,这是管道函数的.参数。封闭的管道函数将在构成adjusted = (filter(treatment!="MOCK")$value)-(filter(treatment=="MOCK")$value)参数的函数调用的参数中出现mutate()的任何地方替换rhs的值,但是不会修改参数。这意味着管道不会尝试隐式提供.参数的值作为对该参数内对.的调用的参数。

由于例如您的电话 rhs被评估为lhs,而不是filter()。仅提供了一个要过滤的参数,因此它在位置上与第一个形式参数filter(treatment!="MOCK")相匹配。 filter(.data = treatment!="MOCK")评估为逻辑值,因为没有S3方法filter(.data = .,treatment != "MOCK"),所以您会出错。您需要将其表示为.data,以使这些函数调用能够访问通过管道传递的treatment!="MOCK"对象。

无论如何,在其他dplyr动词的参数中使用filter.logical动词几乎总是会产生很难推理的代码。有一个原因使您从未在filter(.,treatment!="MOCK")小插曲中看到这一点。也无法针对data.frame SQL后端执行这种操作。

您应该考虑执行联接。我对您的数据结构不完全了解,但似乎每个组只有一个MOCK记录?如果是这样,这样是安全的:

dplyr

请注意,在这种情况下不必进行分组。

,

如果我不太了解“然后我想将每个group_by(day,animalid,name)的值减去我其他“治疗”值(Hp,LP,MLV)的值”,则意味着对于每个组只是两个观察值,一个是treatment=="MOCK",另一个是treatment!="MOCK",则近似值是:

test_valueadj %>%
    mutate(dich_treatment = if_else(treatment != "MOCK","NMOCK","MOCK")) %>%
    group_by(animalid,day,name) %>%
    arrange(dich_treatment) %>%
    mutate(adjusted = lag(value) - value) %>%
    filter(treatment != "MOCK")