在 R 中的两个时间序列之间找到最长的非 NA 公共序列

Find the longest, Non-NA common sequence between two time series in R

假设我有两个不同长度的时间序列。两者都有 timevalue 列。它们在随机位置都有 NA 值。例如:

# Generate first series
series1 <- data.frame(
    time = seq.POSIXt(
        from = as.POSIXct("2020-01-01", origin = "1970-01-01"),
        length.out = 100,
        by = "1 day"
    ),
    value = runif(100, min = 0, max = 100)
)

# Generate second series, which starts and ends and different times
series2 <- data.frame(
    time = seq.POSIXt(
        from = as.POSIXct("2019-12-01", origin = "1970-01-01"),
        length.out = 80,
        by = "1 day"
    ),
    value = runif(80, min = 0, max = 100)
)

# Remove some values at random
random_idx1 <- sample(seq_len(nrow(series1)), 20)
random_idx2 <- sample(seq_len(nrow(series2)), 20)

series1$value[random_idx1] <- NA
series2$value[random_idx2] <- NA

太棒了。如果我要确定每个系列的最大非 NA 序列,我可以使用 stats::na.contiguous()。但是,一个系列的最长序列与另一个系列不同。

现在的问题是:如何确定两个系列之间最长的 重叠 非 NA 值序列?也就是说,两个时间序列之间时间匹配且不是 NA 值的最长值序列是什么?

我们通过 'time' 执行 full_join,在逻辑向量上应用 运行-length-id (rle),即 [=20 的非 NA 元素=]和'value.y',提取'values'为TRUE的lengths,得到max

library(dplyr)
full_join(series1, series2, by = 'time') %>% 
     summarise(len1 = with(rle(!is.na(value.x) &
           !is.na(value.y)), max(lengths[values])))
# len1
#1    5

returns 'series1' 和 'series2' 数据集

中的 'value' 列共有的最大非 NA 元素

问题系列 2 于 2019 年结束,而系列 1 于 2020 年开始,因此没有 运行 个共同的非 NA 值,因此让我们使用末尾注释中给出的不同示例。

1) 仅使用基础 R 我们可以做到这一点:

na.contiguous(merge(DF1, DF2, by = 1))

2) 或者我们可以转换为动物园并做同样的事情。使用 fortify.zoo(z) 转换回来或将其保留为动物园。如果您想要单独的动物园对象,请使用 z$z1 和 z$z2。请注意,time(z) 是结果中的时间。如果时间间隔有规律,也可以使用 ts class:as.ts(z).

library(zoo)
z1 <- read.zoo(DF1)
z2 <- read.zoo(DF2)

z <- na.contiguous(cbind(z1, z2))
z
##   z1 z2
## 3  3 12
## 4  4 13
## 5  5 14
## attr(,"na.action")
## [1] 1 2 6 7
## attr(,"class")
## [1] omit

备注

DF1 <- data.frame(1:6, c(1, 2, 3, 4, 5, NA))
DF2 <- data.frame(2:7, c(NA, 12, 13, 14, 15, 16))