我们如何检测和删除 NA 之间的变量并计算多个时间序列的 ACF?
How can we detect & remove variables with inbetween NAs and calculate the ACF on multiple time series?
这是我的玩具时间序列数据:
library(tidyverse); library(tsibble); library(feasts)
df <- tibble::tribble(
~date, ~A, ~B, ~C,
"1/31/2010", NA, 0.017, NA,
"2/28/2010", NA, 0.027, NA,
"3/31/2010", NA, 0.003, 0.003,
"4/30/2010", -0.022, 0.018, 0.018,
"5/31/2010", -0.036, 0.02, 0.02,
"6/30/2010", -0.046, 0.023, 0.023,
"7/31/2010", NA, 0.027, 0.027,
"8/31/2010", -0.022, 0.008, 0.008,
"9/30/2010", 0.059, -0.003, -0.003,
"10/31/2010", 0.024, 0.058, 0.058,
"11/30/2010", NA, 0.023, NA,
"12/31/2010", NA, 0.014, NA
)
我想计算多个时间序列的自相关 (acf)。忽略插补部分,我需要:
- 删除具有中间 NA 的变量(不是时间序列开始和结束时的变量),例如 NA on 7/31/2010 for A。因此在这种情况下,删除变量 A。
- 可能使用 B 和 C 上 feasts 包中的 ACF 函数计算自相关。
我从这里开始并卡住了:
df %>%
mutate(date = mdy(date)) %>%
pivot_longer(cols = -date) %>%
as_tsibble(key = name, index = date) %>%
ACF()
预期输出将通过滞后对每个可能的序列进行自相关。像 B 一样,10 个滞后值有 10-11 个值,系列 B
也一样
关于第 1 部分
我们可以利用rle
。让我们定义一个简洁的自定义函数 has_middle_NA
has_middle_NA <- function(x) {
rl <- rle(is.na(x))$values
any(rl[-c(1, length(rl))])
}
然后
df %>%
group_by(date) %>%
select_if(~ !has_middle_NA(.x)) %>%
ungroup()
## A tibble: 12 x 3
# date B C
# <chr> <dbl> <dbl>
# 1 1/31/2010 0.017 NA
# 2 2/28/2010 0.027 NA
# 3 3/31/2010 0.003 0.003
# 4 4/30/2010 0.018 0.018
# 5 5/31/2010 0.02 0.02
# 6 6/30/2010 0.023 0.023
# 7 7/31/2010 0.027 0.027
# 8 8/31/2010 0.008 0.008
# 9 9/30/2010 -0.003 -0.003
#10 10/31/2010 0.058 0.058
#11 11/30/2010 0.023 NA
#12 12/31/2010 0.014 NA
这将删除具有 NA
的所有非前导或尾随的列。
关于第 2 部分
根据你提供的数据,我仍然不太清楚你想用 ACF 做什么;但也许这会有所帮助。
关键是把你的数据当作月度数据,忽略天。然后我们可以:
- 使用
zoo::yearmon
、 将您的数据转换为每月数据
- Select 那些“中间”没有
NA
的列,
- 从宽到长转换并从每一列创建一个
tsibble
,
- 使用
feasts::ACF
计算每一列的ACF并将结果存储在tsibble
s 的list
列中
library(tsibble)
library(tidyverse)
library(feasts)
library(zoo)
df <- df %>%
mutate(date = as.yearmon(date, format = "%m/%d/%Y")) %>%
group_by(date) %>%
select_if(~ !has_middle_NA(.x)) %>%
ungroup() %>%
pivot_longer(-date) %>%
group_by(name) %>%
nest() %>%
mutate(
data = map(data, as_tsibble),
ACF = map(data, ACF))
## A tibble: 2 x 3
## Groups: name [2]
# name data ACF
# <chr> <list> <list>
#1 B <tsibble [12 × 2]> <tsibble [10 × 2]>
#2 C <tsibble [12 × 2]> <tsibble [7 × 2]>
这是我的玩具时间序列数据:
library(tidyverse); library(tsibble); library(feasts)
df <- tibble::tribble(
~date, ~A, ~B, ~C,
"1/31/2010", NA, 0.017, NA,
"2/28/2010", NA, 0.027, NA,
"3/31/2010", NA, 0.003, 0.003,
"4/30/2010", -0.022, 0.018, 0.018,
"5/31/2010", -0.036, 0.02, 0.02,
"6/30/2010", -0.046, 0.023, 0.023,
"7/31/2010", NA, 0.027, 0.027,
"8/31/2010", -0.022, 0.008, 0.008,
"9/30/2010", 0.059, -0.003, -0.003,
"10/31/2010", 0.024, 0.058, 0.058,
"11/30/2010", NA, 0.023, NA,
"12/31/2010", NA, 0.014, NA
)
我想计算多个时间序列的自相关 (acf)。忽略插补部分,我需要:
- 删除具有中间 NA 的变量(不是时间序列开始和结束时的变量),例如 NA on 7/31/2010 for A。因此在这种情况下,删除变量 A。
- 可能使用 B 和 C 上 feasts 包中的 ACF 函数计算自相关。
我从这里开始并卡住了:
df %>%
mutate(date = mdy(date)) %>%
pivot_longer(cols = -date) %>%
as_tsibble(key = name, index = date) %>%
ACF()
预期输出将通过滞后对每个可能的序列进行自相关。像 B 一样,10 个滞后值有 10-11 个值,系列 B
也一样关于第 1 部分
我们可以利用rle
。让我们定义一个简洁的自定义函数 has_middle_NA
has_middle_NA <- function(x) {
rl <- rle(is.na(x))$values
any(rl[-c(1, length(rl))])
}
然后
df %>%
group_by(date) %>%
select_if(~ !has_middle_NA(.x)) %>%
ungroup()
## A tibble: 12 x 3
# date B C
# <chr> <dbl> <dbl>
# 1 1/31/2010 0.017 NA
# 2 2/28/2010 0.027 NA
# 3 3/31/2010 0.003 0.003
# 4 4/30/2010 0.018 0.018
# 5 5/31/2010 0.02 0.02
# 6 6/30/2010 0.023 0.023
# 7 7/31/2010 0.027 0.027
# 8 8/31/2010 0.008 0.008
# 9 9/30/2010 -0.003 -0.003
#10 10/31/2010 0.058 0.058
#11 11/30/2010 0.023 NA
#12 12/31/2010 0.014 NA
这将删除具有 NA
的所有非前导或尾随的列。
关于第 2 部分
根据你提供的数据,我仍然不太清楚你想用 ACF 做什么;但也许这会有所帮助。
关键是把你的数据当作月度数据,忽略天。然后我们可以:
- 使用
zoo::yearmon
、 将您的数据转换为每月数据
- Select 那些“中间”没有
NA
的列, - 从宽到长转换并从每一列创建一个
tsibble
, - 使用
feasts::ACF
计算每一列的ACF并将结果存储在tsibble
s 的
list
列中
library(tsibble)
library(tidyverse)
library(feasts)
library(zoo)
df <- df %>%
mutate(date = as.yearmon(date, format = "%m/%d/%Y")) %>%
group_by(date) %>%
select_if(~ !has_middle_NA(.x)) %>%
ungroup() %>%
pivot_longer(-date) %>%
group_by(name) %>%
nest() %>%
mutate(
data = map(data, as_tsibble),
ACF = map(data, ACF))
## A tibble: 2 x 3
## Groups: name [2]
# name data ACF
# <chr> <list> <list>
#1 B <tsibble [12 × 2]> <tsibble [10 × 2]>
#2 C <tsibble [12 × 2]> <tsibble [7 × 2]>