【问题标题】:Interpolate NAs in R with last or next observation by smallest interval用最小间隔插入 R 中的最后一个或下一个观察值的 NA
【发布时间】:2020-04-13 05:55:54
【问题描述】:

我想在两个或多个间隙中使用上一个观察结果向前 (locf) 或下一个观察结果向后 (nocb) 来估算缺失值。

为了确定填充缺失值的方向(上/下),对数据框中的第一列(Interval)进行加权。插值(locf/nocb)应该从最小值结束(对应于向外的 NAs 行的间隔值)。默认的fillna是locf。

示例:异常 nafill 的逻辑:在 ID2 列第 5-7 行(包括标题)中,方向将为 nocb,因为 (Interval[7,] value= 50) 小于 Interval[5,] value= 100。

尝试使用 df1 <-df %>%fill(ID1, ID2, ID3,which.min(Interval)) %>% #default direction down fill(ID1, ID2, ID3, .direction = "up",which.min(Interval)) 无法正常工作,请协助更正它或建议另一种有效的 R 解决方案。预先感谢您的帮助。

输入

df = data.frame(
             Interval = c(0,20,80,100,50,50,130,100,70,80,200), 
             ID1 = c(0,1,1,0,NA,NA,NA,NA,1,NA,1), 
             ID2 = c(1,0,0,NA,NA,NA,1,1,3,NA,1), 
             ID3 = c(1,NA,1,0,3,NA,NA,NA,1,NA,1) 
)

Interval    ID1 ID2 ID3
0   0   1   1
20  1   0   NA
80  1   0   1
100 0   NA  0
50  NA  NA  3
50  NA  NA  NA
130 NA  1   NA
100 NA  1   NA
70  1   3   1
80  NA  NA  NA
200 1   1   1

预期输出

Interval    ID1 ID2 ID3
0   0   1   1
20  1   0   NA
80  1   0   1
100 0   1   0
50  0   1   3
50  0   1   3
130 0   1   3
100 0   1   3
70  1   3   1
80  NA  NA  NA
200 1   1   1

【问题讨论】:

  • 我有点不清楚您希望如何使用 Interval 列来确定方向。能不能把第二段稍微扩展一下?
  • @Glen 我猜你在某种程度上是正确的。检查这个 df %>% fill(ID1, ID2, ID3, .direction = "downup") 。另外,您可以查看以下link
  • 区间列代表物理位置,所以我想推算到更近的位置!间隔本身不是时间序列。我最初尝试添加参数的原因 - which.min(Interval)。例如,ID2 列第 5-7 行中的 NA 应填写 nocb。@hammoire,希望我的解释现在更清楚,谢谢。 @Neel Kamal,感谢您的链接和更正,但不是解决方案。
  • 出于好奇提出一个简短的问题:连续仅填充大于 1 NA 的间隙的原因是什么? R 包 imputeTS 有一个带有 maxgap 选项的 locf 函数。然后,它只会填补小于某个连续 NA 阈值的空白。理由是,间隙越大,locf 越不准确。但是,排除较小差距的插补的原因是什么?
  • 感谢您的观察@stats0007。为了提供背景,我想根据物理位置(间隔)将标记归为更接近的骨架标记的值。在 df 中,例如 ID2 列,Interval 值 50 和 100 都对应于 NA 条目,因此在这种情况下最小的 50 将给出 fillna 方向,即 nocb。稍后我将使用默认 locf 处理单个 NA 条目。

标签: r dplyr tidyverse zoo imputets


【解决方案1】:

尚不清楚您的第一列是做什么用的。您的第二个预期列是locfnocb 的组合,但是您可以逐列使用标准nafill

library(data.table)
apply(df, 2, function(j) {nafill(j, type = "locf")})

根据您的评论,如果您想让nafill依赖于df$Interval,您可以使用以下方法索引您的df

StartIndex <- apply(df[,2:dim(df)[2]], 2, function(j) {
  which(diff(is.na(j)) == 1 ) + 1})
EndIndex <- apply(df[,2:dim(df)[2]], 2, function(j) {
  which(diff(is.na(j)) == -1) })

并指出df$Interval的开始和结束是增加还是减少:

lapply(1:(dim(df)[2]-1), function(i) {
  lapply(1:length(StartIndex[[i]]), function(j) {
    range <- c(StartIndex[[i]][j], EndIndex[[i]][j])
    if (range[1] != range[2]) {
      df$Interval[range[1]] - df$Interval[range[2]]
    }
  })
})

【讨论】:

  • 谢谢@fabian,区间列代表物理位置,所以我想推算到更近的位置!间隔本身不是时间序列。如您所指出的,ID2 列第 5-8 行中的 NA 应填写 nocb。
  • 您的意思是 ID1 第 5-8 行(因为 ID2 的 NA 从 4 到 6 和 10)?那么 nafill 背后的逻辑是什么?
  • 我搞错了,抱歉@fabian。我已将 nafill 背后的逻辑添加到主要问题中,请检查!基本上,Interval 列中的相应值决定了方向是 locf 还是 nocb。我最初尝试添加参数的原因 - which.min(Interval)
  • 好的,但是值 50 和 100 都对应于 NA 条目。那么单个 NA 条目背后的逻辑是什么?
  • 我打赌你是对的@fabian,因为我主要感兴趣的是填补到更接近的物理位置的大间隙,也许忽略单个 NA 条目将是理想的!请忍受我的编程推理。我将更新主要问题。
猜你喜欢
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多