You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用R的modeltime包遇Date索引含NA错误,求解决方案

解决Modeltime时间序列可视化与校准的Date索引NA报错问题

问题描述

使用R的modeltime包进行时间序列分析时,遇到两类核心错误:

  • 可视化数据拆分时触发validate_index()报错,提示Column 'Date' (index) must not contain NA
  • 模型校准阶段所有模型均因相同错误失败

已删除数据集中2个Aluminium_Prices列的NA,但问题仍未解决。相关代码及错误信息如下:

数据处理与拆分代码

# Webscrape
webpage <- read_html("https://www.westmetall.com/en/markdaten.php?action=table&field=LME_Al_cash")
alu_table <- html_nodes(webpage, "table") %>%
  html_table(fill = TRUE)
alu_df <- map_dfr(alu_table, magrittr::extract, c("date", "LME Aluminium Cash-Settlement"))

# Names
names(alu_df)[1] <- "Date"
names(alu_df)[2] <- "Aluminium_Prices"

# Clear rows in data frame 
alu_df_cleaned <- alu_df %>% 
  filter(Date != "date" & Aluminium_Prices != "LME Aluminium Cash-Settlement")

# Change Date type
alu_df_cleaned$Date <- dmy(alu_df_cleaned$Date)

# Proper structure of integers to translate them to the numeric class
alu_df_cleaned$Aluminium_Prices <- gsub(",", "", alu_df_cleaned$Aluminium_Prices)
alu_df_cleaned$Aluminium_Prices <- as.numeric(alu_df_cleaned$Aluminium_Prices)

# Sorting prices by Date
alu_df_cleaned <- alu_df_cleaned %>% 
  arrange(Date)

# Check if there are any NA's 
sum(is.na(alu_df_cleaned$Aluminium_Prices))

df_na <- as.data.frame(
  cbind(
    map(
      map(alu_df_cleaned$Aluminium_Prices, is.na), sum)
    )
  )

rownames(subset(df_na, df_na$V1 != 0))

# Convert to tibble
alu_ts_data <- alu_df_cleaned %>% 
  mutate(row_name = row_number()) %>% 
  tsibble::as_tsibble(index = Date, key = row_name)

# Drop NA's from the dataset
alu_ts_data <- alu_ts_data %>% 
  drop_na()

# Split the data into train and test 
set.seed(1353)
splits <- initial_time_split(alu_ts_data)

train <- training(splits)
test <- testing(splits)

# Visualise the Splits
splits %>% 
  tk_time_series_cv_plan() %>% 
  plot_time_series_cv_plan(.date_var = Date,
                           .value = Aluminium_Prices)

可视化报错信息

Error in `validate_index()`:
! Column `Date` (index) must not contain `NA`.
Backtrace:
  1. splits %>% tk_time_series_cv_plan() %>% ...
 10. tidyr:::unnest.data.frame(., .value)
 11. tidyr::unchop(...)
 12. tidyr:::df_unchop(...)
 13. vctrs::list_unchop(col, ptype = col_ptype)
 14. vctrs (local) `<fn>`()
 16. tsibble:::vec_restore.tbl_ts(x = x, to = to)
 17. tsibble::build_tsibble(...)
 18. tsibble:::validate_index(tbl, !!qindex)
Error in validate_index(tbl, !!qindex) :

模型校准代码与报错

# Multiple models
# Auto ARIMA Model
arima_auto_fit <- arima_reg() %>% 
  set_engine("auto_arima") %>% 
  fit(Aluminium_Prices ~ Date, data = train)

# Boosted ARIMA Model 
arima_boost_fit <- arima_boost() %>% 
  set_engine("auto_arima_xgboost") %>% 
  fit(Aluminium_Prices ~ Date, data = train)

# Exponential Smoothing Model 
ets_fit <- exp_smoothing() %>% 
  set_engine("ets") %>% 
  fit(Aluminium_Prices ~ Date, data = train)

# Prophet Model 
prophet_fit <- prophet_reg() %>% 
  set_engine("prophet") %>% 
  fit(Aluminium_Prices ~ Date, data = train)

# Linear Model 
lm_fit <- linear_reg() %>% 
  set_engine("lm") %>% 
  fit(Aluminium_Prices ~ Date, data = train)

# Put in Table and Calibrate
models_tbl <- modeltime_table(
  arima_auto_fit,
  arima_boost_fit,
  ets_fit,
  prophet_fit,
  lm_fit
)

# Calibrate 
calibrate_tbl <- models_tbl %>% 
  modeltime::modeltime_calibrate(new_data = test, quiet = FALSE)
Error: Column `Date` (index) must not contain `NA`.
Error: Column `Date` (index) must not contain `NA`.
Error: Column `Date` (index) must not contain `NA`.
Error: Column `Date` (index) must not contain `NA`.
Error: Column `Date` (index) must not contain `NA`.

── Model Calibration Failure Report ────────────────────────
All models failed Modeltime Calibration:
- Model 1: Failed Calibration.
- Model 2: Failed Calibration.
- Model 3: Failed Calibration.
- Model 4: Failed Calibration.
- Model 5: Failed Calibration.

Potential Solution: Use `modeltime_calibrate(quiet = FALSE)` AND Check the Error/Warning Messages for clues as to why your model(s) failed calibration.
── End Model Calibration Failure Report ────────────────────

Error in `validate_modeltime_calibration()`:
! All models failed Modeltime Calibration.
Backtrace:
 1. models_tbl %>% ...
 3. modeltime:::modeltime_calibrate.mdl_time_tbl(...)
 4. modeltime:::validate_modeltime_calibration(ret)
Error in validate_modeltime_calibration(ret)

排查原因

  1. 仅检查数值列NA,忽略Date列:代码中只验证了Aluminium_Prices的NA,但dmy()转换日期时可能因格式不匹配生成NA,这些NA未被检测处理。
  2. tsibble的key设置不合理:单变量时间序列无需设置key = row_name,这会让tsibble识别为多序列,后续拆分处理时出现索引混乱。
  3. drop_na()处理不彻底:原代码中drop_na()默认删除含NA的行,但Date列的NA可能在转换为tsibble后才暴露,未被彻底清理。

解决方案

步骤1:全面检查并清理Date列的NA

替换原有NA检查代码,同时验证Date列:

# 检查所有列的NA数量
colSums(is.na(alu_df_cleaned))

# 仅保留Date和Aluminium_Prices均非NA的行
alu_df_cleaned <- alu_df_cleaned %>%
  filter(!is.na(Date) & !is.na(Aluminium_Prices))

步骤2:修正tsibble转换逻辑

单变量时间序列无需设置key,直接转换:

# 转换为tsibble(单序列无需key)
alu_ts_data <- alu_df_cleaned %>% 
  tsibble::as_tsibble(index = Date)

步骤3:重新执行数据拆分与后续操作

# 重新拆分数据
set.seed(1353)
splits <- initial_time_split(alu_ts_data)

train <- training(splits)
test <- testing(splits)

# 验证训练集和测试集的Date列无NA
sum(is.na(train$Date))
sum(is.na(test$Date))

# 重新可视化拆分
splits %>% 
  tk_time_series_cv_plan() %>% 
  plot_time_series_cv_plan(.date_var = Date, .value = Aluminium_Prices)

# 重新训练模型并校准
models_tbl <- modeltime_table(
  arima_auto_fit,
  arima_boost_fit,
  ets_fit,
  prophet_fit,
  lm_fit
)

calibrate_tbl <- models_tbl %>% 
  modeltime::modeltime_calibrate(new_data = test, quiet = FALSE)

额外验证:检查日期格式一致性

确保所有日期转换成功,无异常值:

# 查看Date列的范围和类型
range(alu_df_cleaned$Date)
class(alu_df_cleaned$Date)

# 检查是否有无法转换的日期字符串
bad_dates <- alu_df %>%
  filter(Date != "date") %>%
  mutate(Date_parsed = dmy(Date, quiet = TRUE)) %>%
  filter(is.na(Date_parsed))
print(bad_dates)

内容的提问来源于stack exchange,提问作者AmAzing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 04:21:48