如何在丢失的数据行数超过X的值之间防止插值?

时间:2019-04-19 17:19:29

标签: r dplyr tidyverse

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

我以前发布了一个问题,并得到了很好的答案(How do I prevent interpolation between values where there are more than 2 missing rows of data?)。但是,我简化了示例数据框,现在当我尝试运行代码时,在最后一步中出现此错误:

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步:将近似函数应用于目标列(使用线性插值对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:对所有数据中的所有列应用ContinuousNA函数,并将结果转换为矩阵:

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

第4步:基于m_NA在alldata_int中用NA替换那些TRUE,然后完成工作:

alldata_int[m_NA] <- NA

运行步骤4时,出现此错误:

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

我认为这是因为时间戳列左侧还有其他非数字列。有没有简单的方法可以调整此代码以解决此问题?还是更好的解决方案?

2 个答案:

答案 0 :(得分:3)

zoo包中的

na.approx具有一个maxgap参数:

library(zoo)

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

答案 1 :(得分:1)

由于alldata_int,您的year(r_timestamp)有另外一列group_by。您必须删除该列以使alldata_intm_NA具有相同的尺寸。以下对我有用。

顺便说一句,year可能来自lubridate软件包。最好提供功能的来源。

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"]])) %>%
  ungroup() %>%
  select(-`year(r_timestamp)`)

alldata_int[m_NA] <- NA