根据组中的可用值填充缺失值

Fill missing values based on available values in a group

我想填补缺失值不是基于 LOCF,而是基于该组可用的值。虽然我能够根据 的回答做到这一点,但我正在寻找关于 :

的解释

问题a)(Final_Rank = Final_Rank[1])。楼主没有解释这部分。

问题b)还有其他更高效(速度方面)的方法吗?我看到一个使用 Data.Table,但我不太熟悉它。我无法使用 Data.Table 执行此操作。实际数据大小为 2GB。

这是我的数据:

dput(DF)
structure(list(SL3 = c("SE", "SE", "SE", "SE", "SE", "SE", "SW", 
"SW", "SW", "SW", "SW", "SW"), SL6 = c("SL123", "SL123", "SL123", 
"SL123", "SL123", "SL124", "SL123", "SL123", "SL123", "SL123", 
"SL123", "SL124"), Sname = c("123 Inc", "123 Inc", "123 Inc", 
"123 Inc", "123 Inc", "234 Inc", "345 Inc", "345 Inc", "345 Inc", 
"345 Inc", "345 Inc", "567 Inc"), Group = c("Red", "Sapphire", 
"Red", "Sapphire", "White", "Red", "Red", "Sapphire", "Red", 
"Sapphire", "White", "Red"), Final_Rank = c("High", "Medium", 
NA, NA, "Low", NA, "High", "Medium", NA, NA, "Low", NA), Value = c(1, 
2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6)), .Names = c("SL3", "SL6", "Sname", 
"Group", "Final_Rank", "Value"), row.names = c(NA, 12L), class = "data.frame")

这是我的代码:

DF%>% 
  dplyr::group_by(SL3,SL6, Sname, Group) %>%
  dplyr::arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
  dplyr::mutate(Final_Rank = Final_Rank[1])

预期输出:

     SL3   SL6   Sname    Group Final_Rank Value
   <chr> <chr>   <chr>    <chr>      <chr> <dbl>
1     SE SL123 123 Inc      Red       High     1
2     SE SL123 123 Inc      Red       High     3
3     SE SL123 123 Inc Sapphire     Medium     2
4     SE SL123 123 Inc Sapphire     Medium     4
5     SE SL123 123 Inc    White        Low     5
6     SE SL124 234 Inc      Red       <NA>     6
7     SW SL123 345 Inc      Red       High     1
8     SW SL123 345 Inc      Red       High     3
9     SW SL123 345 Inc Sapphire     Medium     2
10    SW SL123 345 Inc Sapphire     Medium     4
11    SW SL123 345 Inc    White        Low     5
12    SW SL124 567 Inc      Red       <NA>     6

正如我们在上面看到的,因为第 12 行和第 6 行在别处不存在 Final_Rank,所以我会得到 NA。如果我使用 tidyr::fill(),那些就会被填满。

如果有人能帮我解决以上两个问题,我将不胜感激。

对于 A 部分,这是@Haboryme 的评论(保留在答案中):

Final_Rank = Final_Rank[1] simply replaces Final_Rank with the first value of Final_Rank. If there is a non-NA it will be the first. – Haboryme

稍微扩展一下,当使用 group_by 时,它将 select 组 中 Final_Rank 的第一个条目。这只是第一个,因为您在代码中被 Final_Rank arrange'ing。您可以将 Final_Rank[1] 替换为任何选定的值,包括常量(例如 "Missing")或计算值(例如 paste(Final_Rank %>% unique %>% sort, sep ="; ") 以连接该组中的所有值)。

看看时间,mutate描述的方法已经很不错了。 data.table 解决方案往往会快一点,但我发现语法非常困难,以至于我在 run-time 削减的时间在 coding/debugging(然后是一些)中丢失了,除非我是 运行代码一个lot.

这是当前 mutate 解决方案的快速基准测试(使用 microbenchmark 包),建议的 fill 解决方案,以及生成 "look up table" 的解决方案所需的条目,然后将其重新加入。请注意,如果有不止一个有效的 Final_Rank 条目,fill 将给出与其他条目不同的答案。

library(microbenchmark)

microbenchmark(
  mutate =
    DF%>% 
    group_by(SL3,SL6, Sname, Group) %>%
    arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
    mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))
  , fill =
    DF%>% 
    group_by(SL3,SL6, Sname, Group) %>%
    arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
    fill(Final_Rank)
  , left_join =
    DF%>% 
    select(-Value) %>%
    group_by(SL3,SL6, Sname, Group) %>%
    arrange(Final_Rank) %>%
    slice(1) %>%
    rename(newRank = Final_Rank) %>%
    left_join(DF, .) %>%
    arrange(SL3,SL6, Sname, Group)

)

给予

Unit: milliseconds
      expr      min       lq     mean   median       uq      max neval
    mutate 1.783668 1.848683 1.954992 1.904577 1.968923 3.093098   100
      fill 3.299220 3.399997 3.558219 3.491215 3.573784 4.756986   100
 left_join 3.097166 3.214982 3.379452 3.300272 3.420206 4.653970   100

请注意,mutate 解决方案比其他两个解决方案快一点,尽管可能存在其他解决方案(如果组规模增长,这些解决方案的规模可能会有所不同)。

最后,请注意当前的实现将 Final_Rank 中的 ALL 条目替换为组中的第一个条目。如果您只想替换 缺失的 条目,则需要使用 ifelse(或 fill,如上所述),如下所示:

DF%>% 
  group_by(SL3,SL6, Sname, Group) %>%
  arrange(SL3,SL6, Sname, Group, Final_Rank) %>%
  mutate(Final_Rank = ifelse(is.na(Final_Rank), Final_Rank[1], Final_Rank))

我将其添加到 microbenchmark 并且它似乎并没有显着降低速度:

Unit: milliseconds
      expr      min       lq     mean   median       uq      max neval
    mutate 1.752267 1.835038 1.937181 1.900086 1.946848 3.197292   100
      fill 3.289838 3.414916 3.626607 3.507186 3.618336 5.857506   100
 left_join 3.052692 3.209808 3.371702 3.260593 3.377899 6.924646   100
    ifelse 1.771460 1.813426 1.935845 1.883497 1.951977 3.113328   100