首页 > 解决方案 > 如何防止在缺失数据行数超过 X 的值之间进行插值?

问题描述

我想插入丢失的数据,但跳过丢失数据行数超过 X(例如 3)的场景。我有下面的代码,但最后一步不起作用。

我之前发布了一个问题并得到了很好的答案(如何防止在缺少 2 行以上数据的值之间进行插值?)。但是,我过度简化了示例数据框,现在当我尝试运行代码时,在最后一步出现此错误:

Error in `[<-.data.frame`(`*tmp*`, m_NA, value = NA) : unsupported matrix index in replacement

有没有一种简单的方法来调整下面的代码来处理这个问题?还是有更好的解决方案?

这是我的数据的一个子集:

alldata <- structure(list(q_cms = c(0.157, 0.154, 0.154, 0.151, 0.144, 0.151, 
0.151, 0.154, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, 0.157, 0.144, NA), site = c("Wade", "Wade", "Wade", "Wade", 
"Wade", "Wade", "Wade", "Wade", "Wade", "Wade", "Wade", "Wade", 
"Wade", "Wade", "Wade", "Wade", "Wade", "Wade", "Wade", "Wade", 
"Wade", "Wade", "Wade", "Wade", "Wade"), r_timestamp = structure(c(1479691800, 
1479692700, 1479693600, 1479694500, 1479695400, 1479696300, 1479697200, 
1479698100, 1479698160, 1479698220, 1479698280, 1479698340, 1479698400, 
1479698460, 1479698520, 1479698580, 1479698640, 1479698700, 1479698760, 
1479698820, 1479698880, 1479698940, 1479699000, 1479699900, 1479699960
), class = c("POSIXct", "POSIXt"), tzone = "Etc/GMT-4"), NO3_mgNL = c(0.0351, 
NA, NA, NA, NA, NA, NA, NA, 0.0316, 0.0309, 0.0309, 0.03, 0.029, 
0.0297, 0.0278, 0.0278, 0.0304, 0.0292, 0.0267, 0.0282, 0.0293, 
0.0313, 0.0306, NA, 0.0311), DOC_mgL = c(1.854, NA, NA, NA, NA, 
NA, NA, NA, 1.85, 1.843, 1.836, 1.822, 1.802, 1.836, 1.797, 1.808, 
1.817, 1.815, 1.813, 1.813, 1.824, 1.826, 1.82, NA, 1.831)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -25L))

这是我要执行的代码。在此示例中,我试图跳过有 3 个或更多连续缺失数据行的插值:

所需软件包:

library('tidyverse')
library('lubridate')

第 1 步:创建一个函数,continuousNA,它可以根据阈值(由参数 len 指定)识别向量中的连续 NA:

consecutiveNA <- function(x, len = 3){
  rl <- rle(is.na(x))
  logi <- rl$lengths >= len & rl$values
  rl$values <- logi
  inver <- inverse.rle(rl)
  return(inver)
}

第 2 步:将 approx 函数应用于目标列(使用线性插值对 NA 进行插值):

alldata_int <- alldata %>%
  arrange(site, r_timestamp) %>%
  group_by(site, year(r_timestamp)) %>%
  mutate_at(vars(c(NO3_mgNL, DOC_mgL)),
            funs(approx(r_timestamp, ., r_timestamp, rule=1, method="linear")[["y"]]))

第 3 步:对 alldata 中的所有列应用 ContinuousNA 函数,并将结果转换为矩阵:

m_NA <- map(alldata, consecutiveNA, len = 3) %>%
  as.data.frame() %>%
  as.matrix()

第四步:根据m_NA将alldata_int中的那些TRUE替换为NA,然后工作就完成了:

alldata_int[m_NA] <- NA

当我运行第 4 步时,我收到此错误:

Error in `[<-.data.frame`(`*tmp*`, m_NA, value = NA) : unsupported matrix index in replacement

我认为这是因为时间戳列左侧的附加非数字列。有没有一种简单的方法来调整这段代码来处理这个问题?还是更好的解决方案?

标签: rdplyrtidyverse

解决方案


na.approxzoo包里有个maxgap说法:

library(zoo)

ok <- sapply(alldata, is.numeric)
replace(alldata, ok, lapply(alldata[ok], na.approx, maxgap = 2, na.rm = FALSE))

推荐阅读