【问题标题】:Fill in missing values (nacof/nocb) in character column by group按组填写字符列中的缺失值(nacof/nocb)
【发布时间】:2020-08-14 18:34:51
【问题描述】:

假设我有这样的数据集:

   Object       date date_data
 1:      N       <NA>          
 2:      A       <NA>          
 3:      A       <NA>          
 4:      A 2020-01-01 something
 5:      B       <NA>          
 6:      B       <NA>          
 7:      B 2020-01-01 something
 8:      C       <NA>          
 9:      C       <NA>          
10:      C 2020-01-01 something

生成者

example <- data.table(Object = rep(LETTERS[1:3], each=3), date = as.Date(rep(c(NA,NA,"2020-01-01"),3)), date_data = rep(c("","","something")))
example <- rbind(list(Object="N", date=as.Date(NA), date_data = ""), example)

我知道我可以使用 nafill 为每个组填写缺失的日期:

example[, date:= nafill(date,"nocb"), by=Object]
    Object       date date_data
 1:      N       <NA>          
 2:      A 2020-01-01          
 3:      A 2020-01-01          
 4:      A 2020-01-01 something
 5:      B 2020-01-01          
 6:      B 2020-01-01          
 7:      B 2020-01-01 something
 8:      C 2020-01-01          
 9:      C 2020-01-01          
10:      C 2020-01-01 something

我想做的是用与日期列相同的方式填写date_data列。我不能使用数据表的 nafill 选项来做到这一点,因为它不适用于字符值。

什么是简单的解决方法?我看过类似的问题,但没有找到任何涉及相同问题的问题

编辑

@Ronak Shah 的 data.table 适用于原始示例。但是如果我把它改成

example <- data.table(Object = c(rep("A",6), rep("B",3)), date = as.Date(rep(c(NA,NA,"2020-01-01"),3)), date_data = rep(c("","","something")))
example <- rbind(list(Object="N", date=as.Date(NA), date_data = ""), example)


   Object       date date_data
 1:      N       <NA>          
 2:      A       <NA>          
 3:      A       <NA>          
 4:      A 2020-01-01 something
 5:      A       <NA>          
 6:      A       <NA>          
 7:      A 2020-01-01 something
 8:      B       <NA>          
 9:      B       <NA>          
10:      B 2020-01-01 something

na.fill 不再起作用,我收到错误消息:提供了 4 个项目以分配给“date_data”列中大小为 6 的组 2。 RHS 长度必须为 1(单个值即可)或与 LHS 长度完全匹配。如果您希望“回收”RHS,请明确使用 rep() 向您的代码读者明确说明这一意图。

【问题讨论】:

  • 你可以看看tidyr::fill(),zoo::na.locf()
  • 你可以尝试转换为因子然后使用data.table nafill函数

标签: r string data.table grouping na


【解决方案1】:

您可以用NA 替换空值并使用zoo::na.locf

library(data.table)

example[, date_data := zoo::na.locf(replace(date_data, date_data == "", NA)), Object]
example

#   Object       date date_data
# 1:      N       <NA>          
# 2:      A 2020-01-01 something
# 3:      A 2020-01-01 something
# 4:      A 2020-01-01 something
# 5:      B 2020-01-01 something
# 6:      B 2020-01-01 something
# 7:      B 2020-01-01 something
# 8:      C 2020-01-01 something
# 9:      C 2020-01-01 something
#10:      C 2020-01-01 something

同样使用tidyrfill

library(dplyr)

example %>%
  mutate(date_data = replace(date_data, date_data == "", NA)) %>%
  group_by(Object) %>%
  tidyr::fill(date_data, .direction = "up")

【讨论】:

  • 谢谢,第一个选项解决了!您知道为什么以下内容不起作用:example[, date_data:=replace(date_data, date_data == "", NA)][ ,date_data := tidyr::fill(date_data, .direction="up") , by = 对象]
  • 是的,因为fill 需要第一个参数作为数据框,所以您传递的是一个向量date_data
  • 还有什么方法可以使用填充并仍将输出作为 data.table 获得? (当然,我可以使用您编写的内容并将其转换为 data.table ,但这并不整洁,并且会减慢我的代码速度)。当 NA/s 和字符值在组内交换时,Na.fill 不适用于我的分组
  • @Djpengo 在na.locf 中有fromLast 参数,您可以在此处使用。 example[, date_data := zoo::na.locf(replace(date_data, date_data == "", NA), fromLast = TRUE), Object]
  • 是的,实际上这也让我感到困惑,但帮助页面中的示例显示了它们的行为差异。 bz &lt;- c(2,NA,1,4,5,2)na.locf(bz)na.locf(bz, fromLast = TRUE)
【解决方案2】:

另一个使用data.table 的选项同时应用于所有类型的列:

#change empty string to NAs if there are more columns, use set
example[date_data=="", date_data := NA_character_]

cols <- c("date", "date_data")
example[, (cols) := lapply(.SD, 
      function(x) x[nafill(replace(seq.int(.N), is.na(x), NA_integer_), "nocb")]), 
  Object, .SDcols=cols]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多