group_by() 进入 fill() 未按预期工作

group_by() into fill() not working as expected

我正在尝试使用 dplyrtidyr 对一些格式不正确的数据执行上次观察结转操作。它没有像我预期的那样工作。

library(dplyr)
library(tidyr)

df <- data.frame(id=c(1,1,2,2,3,3),
                 email=c('bob@email.com', NA, 'joe@email.com', NA, NA, NA))
df2 <- df %>% group_by(id) %>% fill(email)

这导致:

Source: local data frame [6 x 2]
Groups: id [3]

     id         email
  (dbl)        (fctr)
1     1 bob@email.com
2     1 bob@email.com
3     2 joe@email.com
4     2 joe@email.com
5     3 joe@email.com
6     3 joe@email.com

我希望它是:

Source: local data frame [6 x 2]
Groups: id [3]

     id         email
  (dbl)        (fctr)
1     1 bob@email.com
2     1 bob@email.com
3     2 joe@email.com
4     2 joe@email.com
5     3 NA
6     3 NA

我希望它是后者的原因是因为 group_by 的文档说,"The group_by function takes an existing tbl and converts it into a grouped tbl where operations are performed "by group"。"本例中的分组是由id变量决定的,下面的操作就是fill(email)。但是,很明显它没有这样做。


在任何人问之前,如果字段都是 character 而不是 numericfactor.

没有区别

更新 @aosmith 在 Github 上指出 this open issue。我要说的是,在解决该问题之前,不会有适当的解决方案。其他一切都只是一种解决方法。因此,如果有人成功地通过 PR 解决了该问题并将其发布在这里,我很乐意将其标记为解决方案。

两个问题,是不是重复了,一定要用dplyrtidyr

也许这是一个解决方案?

(
bar <- data.frame(id=c(1,1,2,2,3,3),
                 email=c('bob@email.com', NA, 'joe@email.com', NA, NA, NA))
)                 
#> id         email
#>  1 bob@email.com
#>  1          <NA>
#>  2 joe@email.com
#>  2          <NA>
#>  3          <NA>
#>  3          <NA>

(                 
foo <- bar[!duplicated(bar$id),]
)
#> id         email
#>  1 bob@email.com
#>  2 joe@email.com
#>  3          <NA>

幸运的是,您仍然可以为此使用 zoo::na.locf

df %>% 
    group_by(id) %>% 
    mutate(email = zoo::na.locf(email, na.rm = FALSE))  
# Source: local data frame [6 x 2]
# Groups: id [3]
# 
#      id         email
#   (dbl)        (fctr)
# 1     1 bob@email.com
# 2     1 bob@email.com
# 3     2 joe@email.com
# 4     2 joe@email.com
# 5     3            NA
# 6     3            NA

这有点难看,但它是另一个使用 dplyr 并使用您的示例数据的选项

df %>%
   group_by(id) %>%
   mutate(email = email[ !is.na(email) ][1])

另一种选择是使用 do 来自 dplyr:

df3 <- df %>% group_by(id) %>% do(fill(.,email))

看起来这已在 tidyr 的开发版本中得到修复。您现在使用 fill 从 tidyr_0.3.1.9000.

获得每个 id 的预期结果
df %>% group_by(id) %>% fill(email)

Source: local data frame [6 x 2]
Groups: id [3]

     id         email
  (dbl)        (fctr)
1     1 bob@email.com
2     1 bob@email.com
3     2 joe@email.com
4     2 joe@email.com
5     3            NA
6     3            NA

这个问题我遇到过好几次了,我很担心这个问题..

df2 <- df %>% group_by(id) %>% fill(email)

在大型数据集上,因为我得到了不同的结果,并找到了以下解决方法。与 map_df 一起使用的 split 函数可确保您将所做的任何事情应用到每个 id 的特定 df,然后 map_df 像魔术一样重新绑定所有单独的 df。它也被证明在许多其他情况下很方便。现在这个问题有点过时了,但仍然是避免 group_by() 的有用替代方法。

df %>% split(.$id) %>% map_df(function(x){ x %>% fill(email)})