group_by()到fill()没有按预期工作

时间:2015-12-29 19:03:29

标签: r dplyr tidyr

我尝试使用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的文档说,&#34; group_by函数采用现有的tbl并将其转换为分组的tbl在哪里进行操作&#34;按组&#34;。&#34;在这种情况下,组由id变量确定,以下操作为fill(email)。但是,它显然不是那样做的。

在任何人提出要求之前,如果字段都是character而不是numericfactor,则没有任何区别。

更新 @aosmith在Github上指出了this open issue。我要说的是,在问题得到解决之前,不能解决这个问题。其他一切都只是一种解决方法。所以,如果有人成功解决了这个问题,并将其发布在此处,我很乐意将其标记为解决方案。

6 个答案:

答案 0 :(得分:10)

tidyr 的开发版本中已经修复了这个问题。现在,您可以使用来自tidyr_0.3.1.9000的fill获得每个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

答案 1 :(得分:6)

幸运的是,您仍然可以使用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

答案 2 :(得分:2)

另一种选择是使用RecyclerView中的DialogFragment

do

答案 3 :(得分:0)

有两个问题,是否重复,您是否必须使用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>

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

我已经多次遇到这个问题了,我确实担心使用此问题。

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)})