【问题标题】:Fill missing values based on available values in a group根据组中的可用值填充缺失值
【发布时间】:2017-02-02 08:53:02
【问题描述】:

我想填充缺失值,而不是基于 LOCF,而是基于该组可用的值。虽然我能够根据Filling missing value in group 的回答做到这一点,但我正在寻找有关以下方面的解释:

问题 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(),那些会被填满。

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

【问题讨论】:

  • Final_Rank = Final_Rank[1] 只是将Final_Rank 替换为Final_Rank 的第一个值。如果有非 NA,它将是第一个。
  • @Haboryme - 感谢您的帮助...您能解释一下“第一个”值是什么意思吗?您是指分组集中的第一个值吗?如果是这样,那么通过Final_Rank[2],我应该得到一些数字和一些NAs,但我得到所有NAs。不知道为什么。
  • 你会得到所有的 NA,因为当你订购时,NA 总是最后的(试试x &lt;- c(1, 2, NA, 6, 11, NA, 9); x[order(x)])。因此,如果您有 2 个值,它们是 c('High', NA),那么 Final_Rank[2] == NA。另一方面,如果您只有 1 个值(即 c('High')),那么尝试获取第二个元素(使用 Final_Rank[2])将导致 NA(因为它不存在)。
  • @Sotos 我认为其中一个有 2 个非 NA 值,我误读了。那么这是有道理的,ty。
  • 我再问一遍:你目前的做法不正确怎么办?您想要改变的只是速度,还是有其他原因?

标签: r dplyr tidyr


【解决方案1】:

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

Final_Rank = Final_Rank[1] 只是将Final_Rank 替换为Final_Rank 的第一个值。如果有非 NA,它将是第一个。 – Haboryme

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

单看时间,所描述的mutate方法已经相当不错了。 data.table 解决方案往往要快一些,但我发现语法足够困难,以至于我在运行时剃掉的时间会在编码/调试(然后是一些)中丢失,除非我正在运行代码 lot。

这里是当前mutate 解决方案的快速基准测试(使用microbenchmark 包),建议使用fill 解决方案,以及生成带有所需条目的“查找表”的解决方案,然后将其加入请注意,如果有多个有效的 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 条目替换为组中的第一个条目。如果您只想替换 missing 条目,则需要使用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

【讨论】:

    猜你喜欢
    • 2020-04-13
    • 2016-08-26
    • 2020-10-01
    • 1970-01-01
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 2022-11-30
    • 1970-01-01
    相关资源
    最近更新 更多