使用数据框中的缺失值创建 ts 时间序列
Creating a ts time series with missing values from a data frame
我有一个包含每月数据时间序列的数据框,其中有一些缺失值。
dates <- seq(
as.Date("2010-01-01"), as.Date("2017-12-01"), "1 month"
)
n_dates <- length(dates)
dates <- dates[runif(n_dates) < 0.5]
time_data <- data.frame(
date = dates,
value = rnorm(length(dates))
)
## date value
## 1 2010-02-01 1.3625419
## 2 2010-06-01 0.1512481
## etc.
为了能够在 forecast
中使用时间序列预测功能,我想将其转换为 ts
对象。
执行此操作的愚蠢方法是在整个时间段内创建一组规则的月度日期,然后左连接回到原始数据。
library(dplyr)
first_date <- min(time_data$date)
last_date <- max(time_data$date)
full_dates <- data.frame(
date = seq(first_date, last_date, "1 month")
)
extended_time_data <- left_join(full_dates, time_data, by = "date")
## date value
## 1 2010-02-01 1.3625419
## 2 2010-03-01 NA
## etc.
现在我可以使用 ts()
创建时间序列。
library(lubridate)
time_series <- ts(
extended_time_data$value,
start = c(year(first_date), month(first_date)),
frequency = 12
)
对于这样一个简单的任务,这是冗长且非常恶心的。
我也研究过首先转换为 xts
,并使用 timetk
包中的转换器,但我没有想到更简单的方法。
这个问题是 How to create time series with missing datetime values 的骗局,但那里的答案更加模糊。
如何根据缺少值的时间序列创建 ts
对象?
不使用 left_join
,更简单的选择是 complete
,将其转换为现在与 forecast
包函数兼容的 tsibble
对象
library(tidyverse)
library(tsibble)
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month"),
fill = list(value = NA)) %>%
as_tsibble(index = date)
# A tsibble: 94 x 2 [1D]
# date value
# <date> <dbl>
# 1 2010-02-01 1.02
# 2 2010-03-01 NA
# 3 2010-04-01 NA
# 4 2010-05-01 1.75
# 5 2010-06-01 NA
# 6 2010-07-01 NA
# 7 2010-08-01 -0.233
# 8 2010-09-01 NA
# 9 2010-10-01 NA
#10 2010-11-01 -0.987
# ... with 84 more rows
如上所述,它与 forecast
函数兼容
library(fable)
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month"),
fill = list(value = 0)) %>%
as_tsibble(index = date) %>%
ETS(value) %>%
forecast %>%
autoplot
注意:此处,缺失值被估算为 0。
可以用fill
之前的非NA值来估算
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month")) %>%
fill(value) %>%
as_tsibble(index = date) %>%
ETS(value) %>%
forecast %>%
autoplot
数据
n_dates <- 3
使用最后注释中定义的输入数据框,将其转换为索引为 class yearmon
的动物园对象。然后 as.ts
将其转换为 ts
.
library(zoo)
z <- read.zoo(DF, FUN = as.yearmon)
as.ts(z)
## Jan Feb Mar Apr May Jun Jul Aug
## 2000 1 NA NA 2 3 NA 4 5
如果你更喜欢用管道来表达:
library(magrittr)
library(zoo)
DF %>% read.zoo(FUN = as.yearmon) %>% as.ts
如果需要,使用 na.locf
(最后一次出现结转)、na.approx
(线性插值)、na.spline
、na.StructTS
(季节性卡尔曼滤波器)或其他动物园 NA 填充功能。例如
library(forecast)
DF %>% read.zoo(FUN = as.yearmon) %>% as.ts %>% na.spline %>% forecast
备注
问题中的数据不可重现,因为使用的随机数没有 set.seed
并且 n_dates
未定义。下面我们定义一个数据框 DF
可重复用于示例目的。
library(zoo)
dates <- as.Date(as.yearmon("2000-01") + c(0, 3, 4, 6, 7)/12)
DF <- data.frame(dates, values = seq_along(dates))
给予:
> DF
dates values
1 2000-01-01 1
2 2000-04-01 2
3 2000-05-01 3
4 2000-07-01 4
5 2000-08-01 5
一个 base
选项并在 运行 数据生成之前使用 set.seed(789)
temp <- which(full_dates$date%in%time_data$date)
full_dates$new[temp] <- time_data$value
head(full_dates, 20)
date new
1 2010-02-01 0.62589399
2 2010-03-01 0.98117664
3 2010-04-01 NA
4 2010-05-01 -0.04770986
5 2010-06-01 -1.51961483
6 2010-07-01 NA
7 2010-08-01 0.79493644
8 2010-09-01 -0.14423251
9 2010-10-01 -0.70649791
10 2010-11-01 0.61071247
11 2010-12-01 NA
12 2011-01-01 1.08506164
13 2011-02-01 -0.71134925
14 2011-03-01 1.15628805
15 2011-04-01 1.23556280
16 2011-05-01 -0.32245531
17 2011-06-01 NA
18 2011-07-01 NA
19 2011-08-01 0.73277540
20 2011-09-01 -0.28752883
或相同结果但使用 data.table
setDT(full_dates)[temp, new:= time_data$value]
现在到xts
xts::xts(full_dates[,-1], order.by = full_dates$date, frequency = 12 )
我有一个包含每月数据时间序列的数据框,其中有一些缺失值。
dates <- seq(
as.Date("2010-01-01"), as.Date("2017-12-01"), "1 month"
)
n_dates <- length(dates)
dates <- dates[runif(n_dates) < 0.5]
time_data <- data.frame(
date = dates,
value = rnorm(length(dates))
)
## date value
## 1 2010-02-01 1.3625419
## 2 2010-06-01 0.1512481
## etc.
为了能够在 forecast
中使用时间序列预测功能,我想将其转换为 ts
对象。
执行此操作的愚蠢方法是在整个时间段内创建一组规则的月度日期,然后左连接回到原始数据。
library(dplyr)
first_date <- min(time_data$date)
last_date <- max(time_data$date)
full_dates <- data.frame(
date = seq(first_date, last_date, "1 month")
)
extended_time_data <- left_join(full_dates, time_data, by = "date")
## date value
## 1 2010-02-01 1.3625419
## 2 2010-03-01 NA
## etc.
现在我可以使用 ts()
创建时间序列。
library(lubridate)
time_series <- ts(
extended_time_data$value,
start = c(year(first_date), month(first_date)),
frequency = 12
)
对于这样一个简单的任务,这是冗长且非常恶心的。
我也研究过首先转换为 xts
,并使用 timetk
包中的转换器,但我没有想到更简单的方法。
这个问题是 How to create time series with missing datetime values 的骗局,但那里的答案更加模糊。
如何根据缺少值的时间序列创建 ts
对象?
不使用 left_join
,更简单的选择是 complete
,将其转换为现在与 forecast
包函数兼容的 tsibble
对象
library(tidyverse)
library(tsibble)
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month"),
fill = list(value = NA)) %>%
as_tsibble(index = date)
# A tsibble: 94 x 2 [1D]
# date value
# <date> <dbl>
# 1 2010-02-01 1.02
# 2 2010-03-01 NA
# 3 2010-04-01 NA
# 4 2010-05-01 1.75
# 5 2010-06-01 NA
# 6 2010-07-01 NA
# 7 2010-08-01 -0.233
# 8 2010-09-01 NA
# 9 2010-10-01 NA
#10 2010-11-01 -0.987
# ... with 84 more rows
如上所述,它与 forecast
函数兼容
library(fable)
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month"),
fill = list(value = 0)) %>%
as_tsibble(index = date) %>%
ETS(value) %>%
forecast %>%
autoplot
注意:此处,缺失值被估算为 0。
可以用fill
time_data %>%
complete(date = seq(min(date), max(date), by = "1 month")) %>%
fill(value) %>%
as_tsibble(index = date) %>%
ETS(value) %>%
forecast %>%
autoplot
数据
n_dates <- 3
使用最后注释中定义的输入数据框,将其转换为索引为 class yearmon
的动物园对象。然后 as.ts
将其转换为 ts
.
library(zoo)
z <- read.zoo(DF, FUN = as.yearmon)
as.ts(z)
## Jan Feb Mar Apr May Jun Jul Aug
## 2000 1 NA NA 2 3 NA 4 5
如果你更喜欢用管道来表达:
library(magrittr)
library(zoo)
DF %>% read.zoo(FUN = as.yearmon) %>% as.ts
如果需要,使用 na.locf
(最后一次出现结转)、na.approx
(线性插值)、na.spline
、na.StructTS
(季节性卡尔曼滤波器)或其他动物园 NA 填充功能。例如
library(forecast)
DF %>% read.zoo(FUN = as.yearmon) %>% as.ts %>% na.spline %>% forecast
备注
问题中的数据不可重现,因为使用的随机数没有 set.seed
并且 n_dates
未定义。下面我们定义一个数据框 DF
可重复用于示例目的。
library(zoo)
dates <- as.Date(as.yearmon("2000-01") + c(0, 3, 4, 6, 7)/12)
DF <- data.frame(dates, values = seq_along(dates))
给予:
> DF
dates values
1 2000-01-01 1
2 2000-04-01 2
3 2000-05-01 3
4 2000-07-01 4
5 2000-08-01 5
一个 base
选项并在 运行 数据生成之前使用 set.seed(789)
temp <- which(full_dates$date%in%time_data$date)
full_dates$new[temp] <- time_data$value
head(full_dates, 20)
date new
1 2010-02-01 0.62589399
2 2010-03-01 0.98117664
3 2010-04-01 NA
4 2010-05-01 -0.04770986
5 2010-06-01 -1.51961483
6 2010-07-01 NA
7 2010-08-01 0.79493644
8 2010-09-01 -0.14423251
9 2010-10-01 -0.70649791
10 2010-11-01 0.61071247
11 2010-12-01 NA
12 2011-01-01 1.08506164
13 2011-02-01 -0.71134925
14 2011-03-01 1.15628805
15 2011-04-01 1.23556280
16 2011-05-01 -0.32245531
17 2011-06-01 NA
18 2011-07-01 NA
19 2011-08-01 0.73277540
20 2011-09-01 -0.28752883
或相同结果但使用 data.table
setDT(full_dates)[temp, new:= time_data$value]
现在到xts
xts::xts(full_dates[,-1], order.by = full_dates$date, frequency = 12 )