【问题标题】:How do I prevent interpolation between values where there are more than X number of missing rows of data?如何防止在缺失数据行数超过 X 的值之间进行插值?
【发布时间】:2019-04-19 17:19:28
【问题描述】:

我想插入缺失的数据,但跳过缺失数据行数超过 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 步:将 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

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

【问题讨论】:

    标签: r dplyr tidyverse


    【解决方案1】:

    zoo 包中的na.approx 有一个maxgap 参数:

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

    【讨论】:

      【解决方案2】:

      由于group_by,您的alldata_int 多了一列year(r_timestamp)。您必须删除该列以使 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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-04-11
        • 1970-01-01
        • 1970-01-01
        • 2015-10-01
        • 2021-12-31
        • 1970-01-01
        • 2018-09-09
        相关资源
        最近更新 更多