dplyr :: mutate给出x/y = NA,总结给出x/y =实数

Ben*_*min 5 r dplyr

我正在努力验证一个函数来计算我实验室中某个标准的通过率.这背后的数学非常简单:给定了许多通过或失败的测试,通过了多少百分比.

数据将作为一列值提供P1(在第一次测试时传递),F1(在第一次测试时失败)P2F2(分别在第二次测试时传递或失败).我编写了passRate下面的函数来帮助计算总体通过率(第一次和第二次尝试)以及第一次测试和第二次测试.

设置验证参数的质量专家给了我一个通过和失败计数的列表,我使用test_vector下面的函数将其转换为向量.

一切都看起来很棒,直到我到达Pass数据框的第三行,其中包含来自我的质量专家的通过/失败计数.它不是返回100%的第二次测试通过率,而是返回NA ...但仅在我使用时返回mutate

library(dplyr)

Pass <- structure(list(P1 = c(2L, 0L, 10L), 
                       F1 = c(0L, 2L, 0L), 
                       P2 = c(0L, 3L, 2L), 
                       F2 = c(0L, 2L, 0L), 
                       id = 1:3), 
                  .Names = c("P1", "F1", "P2", "F2", "id"), 
                  class = c("tbl_df", "data.frame"), 
                  row.names = c(NA, -3L))
Run Code Online (Sandbox Code Playgroud)

所以这里有类似于我所做的事情mutate.

Pass %>%
  group_by(id) %>%
  mutate(pass_rate = (P1 + P2) / (P1 + P2 + F1 + F2) * 100,
         pass_rate1 = P1 / (P1 + F1) * 100,
         pass_rate2 = P2 / (P2 + F2) * 100)

Source: local data frame [3 x 8]
Groups: id [3]

     P1    F1    P2    F2    id pass_rate pass_rate1 pass_rate2
  (int) (int) (int) (int) (int)     (dbl)      (dbl)      (dbl)
1     2     0     0     0     1 100.00000        100         NA
2     0     2     3     2     2  42.85714          0         60
3    10     0     3     1     3 100.00000        100         NA
Run Code Online (Sandbox Code Playgroud)

比较我用的时候 summarise

Pass %>%
  group_by(id) %>%
  summarise(pass_rate = (P1 + P2) / (P1 + P2 + F1 + F2) * 100,
            pass_rate1 = P1 / (P1 + F1) * 100,
            pass_rate2 = P2 / (P2 + F2) * 100)

Source: local data frame [3 x 4]

     id pass_rate pass_rate1 pass_rate2
  (int)     (dbl)      (dbl)      (dbl)
1     1 100.00000        100         NA
2     2  42.85714          0         60
3     3 100.00000        100        100
Run Code Online (Sandbox Code Playgroud)

我原以为这些会返回相同的结果.我的猜测是mutate在某个地方遇到问题,因为它假设n每组的行应该映射到n结果中的行(它在n这里计算时会感到困惑吗?),同时summarise知道无论它开始有多少行,它都会以1.

有没有人对这种行为背后的机制有什么想法?

Car*_*itz 3

在我看来,这似乎是dplyr和之间的一些干扰plyr。我对另一个不平衡的数据集也有同样的问题(因此分组是必要的),而在第三组中,突变变量错误地为 NA!然后我在家里重现了你的例子。首先,之后

library("dplyr", lib.loc="~/R/x86_64-pc-linux-gnu-library/3.2")
Run Code Online (Sandbox Code Playgroud)

我得到了你的准确结果。plyr然后我执行了我自己的脚本,其中已加载包。在警告不要加载之后plyr,我的第三dplyr组中的 NA消失了,并且您的示例计算正确!这是我所做的(我又添加了一行来查看 NA 是否仍保留在第三组中):

> Pass <- structure(list(P1 = c(2L, 0L, 10L,8L), 
+                        F1 = c(0L, 2L, 0L, 4L), 
+                        P2 = c(0L, 3L, 2L, 2L), 
+                        F2 = c(0L, 2L, 0L, 1L), 
+                        id = 1:4), 
+                   .Names = c("P1", "F1", "P2", "F2", "id"), 
+                   class = c("tbl_df", "data.frame"), 
+                   row.names = c(NA, -4L))
> Pass %>%
+     group_by(id) %>%
+     mutate(pass_rate = (P1 + P2) / (P1 + P2 + F1 + F2) * 100,
+            pass_rate1 = P1 / (P1 + F1) * 100,
+            pass_rate2 = P2 / (P2 + F2) * 100)
Source: local data frame [4 x 8]
Groups: id [4]

 P1    F1    P2    F2    id pass_rate pass_rate1 pass_rate2
(int) (int) (int) (int) (int)     (dbl)      (dbl)      (dbl)
 1     2     0     0     0     1 100.00000  100.00000         NA
 2     0     2     3     2     2  42.85714    0.00000   60.00000
 3    10     0     2     0     3 100.00000  100.00000         NA
 4     8     4     2     1     4  66.66667   66.66667   66.66667
Run Code Online (Sandbox Code Playgroud)

然后我做了:

> library("plyr", lib.loc="~/R/x86_64-pc-linux-gnu-library/3.2")
> Pass %>%
+     group_by(id) %>%
+     mutate(pass_rate = (P1 + P2) / (P1 + P2 + F1 + F2) * 100,
+            pass_rate1 = P1 / (P1 + F1) * 100,
+            pass_rate2 = P2 / (P2 + F2) * 100)
Source: local data frame [4 x 8]
Groups: id [4]

 P1    F1    P2    F2    id pass_rate pass_rate1 pass_rate2
(int) (int) (int) (int) (int)     (dbl)      (dbl)      (dbl)
 1     2     0     0     0     1 100.00000  100.00000        NaN
 2     0     2     3     2     2  42.85714    0.00000   60.00000
 3    10     0     2     0     3 100.00000  100.00000  100.00000
 4     8     4     2     1     4  66.66667   66.66667   66.66667
Run Code Online (Sandbox Code Playgroud)

我知道这不是一个令人满意的答案,因为plyr不应在之后加载dplyr但也许它可以帮助那些需要的人group_by(id)。或者使用plyr::mutate(). 然后你可以dplyr在之后加载plyr

 > Pass %>%
+     group_by(id) %>%
+     plyr::mutate(pass_rate = (P1 + P2) / (P1 + P2 + F1 + F2) * 100,
+            pass_rate1 = P1 / (P1 + F1) * 100,
+            pass_rate2 = P2 / (P2 + F2) * 100)
Source: local data frame [4 x 8]
Groups: id [4]

 P1    F1    P2    F2    id pass_rate pass_rate1 pass_rate2
(int) (int) (int) (int) (int)     (dbl)      (dbl)      (dbl)
 1     2     0     0     0     1 100.00000  100.00000        NaN
 2     0     2     3     2     2  42.85714    0.00000   60.00000
 3    10     0     2     0     3 100.00000  100.00000  100.00000
 4     8     4     2     1     4  66.66667   66.66667   66.66667
Run Code Online (Sandbox Code Playgroud)