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

使用randomForest处理汇率分类任务时遇NA错误求助

解决randomForest报错"NA not permitted in predictors"的方案

问题根源分析

你遇到的NA not permitted in predictors错误,核心是建模用的特征数据中存在NA值,结合代码来看,主要来自三个方面:

  1. 指标计算时NA处理不当:计算RSI、MACD等指标时过早用na.omit(),导致这些指标长度短于原始数据,后续手动截取[1:4350]合并时,不足部分自动填充NA。
  2. 标准化代码参数错误:sapply(isa.data, mean, 2)中的2被当作mean函数的trim参数(而非按列计算的标识),导致均值计算完全错误,后续归一化产生NA。
  3. 训练数据与标签长度不匹配:手动截取rfisnorma.data[11:3045,1:15]和na.omit(isdira.data)后,两者长度不一致,且未彻底清理数据中的NA。

分步修正方案

1. 修正指标计算逻辑,避免过早删除NA

去掉na.omit(),用rollapply参数保留对齐后的NA,后续统一处理:

library(priceR)
library(tidyverse)  
library(quantmod) 
library(randomForest)

# 获取汇率数据
a <- historical_exchange_rates("THB", to = "USD", start_date = "2010-01-01", end_date = "2021-12-31")

# 计算技术指标,保留NA后续统一处理
a.avg10 <- rollapply(a[,2], 10, mean, align = "right", fill = NA)
a.avg20 <- rollapply(a[,2], 20, mean, align = "right", fill = NA)
a.std10 <- rollapply(a[,2], 10, sd, align = "right", fill = NA)  # 修正原代码窗口错误(原误用20窗口)
a.std20 <- rollapply(a[,2], 20, sd, align = "right", fill = NA)
a.rsi5 <- RSI(a[,2], 5, "SMA")
a.rsi14 <- RSI(a[,2], 14, "SMA")
a.macd12269 <- MACD(a[,2], 12, 26, 9, "SMA")
a.macd7205 <- MACD(a[,2], 7, 20, 5, "SMA")
a.bbands <- BBands(a[,2], 20, "SMA", 2)

# 创建方向变量
a.direction <- a %>% mutate(direction = ifelse(one_THB_equivalent_to_x_USD - lag(one_THB_equivalent_to_x_USD, 10) <= 0, 0, 1))

2. 合并数据并统一清理NA

用bind_cols对齐列,再用drop_na()一次性删除含NA的行,避免手动截取长度:

# 合并所有特征与标签
a.data <- bind_cols(
  exchange_rate = a[,2],
  avg10 = a.avg10,
  avg20 = a.avg20,
  as.data.frame(a.bbands),
  std10 = a.std10,
  std20 = a.std20,
  rsi5 = a.rsi5,
  rsi14 = a.rsi14,
  as.data.frame(a.macd12269),
  as.data.frame(a.macd7205),
  direction = a.direction$direction
) %>% drop_na()

# 计算分类标签(Up/Down/Nowhere)并合并
a <- a %>% mutate(
  lagret = (one_THB_equivalent_to_x_USD - lag(one_THB_equivalent_to_x_USD, 10))/lag(one_THB_equivalent_to_x_USD, 10),
  rfa_direction = case_when(
    lagret > 0.02 ~ "Up",
    lagret < -0.02 ~ "Down",
    TRUE ~ "Nowhere"
  )
)

a.data <- a.data %>% bind_cols(rfa_direction = a$rfa_direction) %>% drop_na()

3. 修正训练测试集划分与标准化

用scale函数简化标准化,确保训练集和测试集用相同的均值/标准差,同时保证特征与标签长度一致:

# 设置随机种子保证可重复性
set.seed(123)
# 划分训练测试集
split_idx <- sample(c(rep(0, round(0.7*nrow(a.data))), rep(1, round(0.3*nrow(a.data)))))
train_data <- a.data[split_idx == 0,]
test_data <- a.data[split_idx == 1,]

# 分离特征与标签
train_features <- train_data %>% select(-direction, -rfa_direction)
train_labels <- as.factor(train_data$rfa_direction)
test_features <- test_data %>% select(-direction, -rfa_direction)
test_labels <- as.factor(test_data$rfa_direction)

# 标准化:用训练集的统计量标准化测试集,避免数据泄露
scaled_train <- scale(train_features)
scaled_test <- scale(test_features, 
                     center = attr(scaled_train, "scaled:center"), 
                     scale = attr(scaled_train, "scaled:scale"))

# 转换为数据框
rf_train_features <- as.data.frame(scaled_train)
rf_test_features <- as.data.frame(scaled_test)

4. 重新构建randomForest模型

此时特征数据已无NA,且与标签长度匹配:

rfmodela.data <- randomForest(x = rf_train_features, 
                              y = train_labels, 
                              xtest = rf_test_features, 
                              ytest = test_labels, 
                              ntree = 500, 
                              importance = TRUE)

额外注意事项

  • 始终用set.seed()保证随机划分的可重复性
  • 避免手动截取行号,用drop_na()或complete.cases()统一处理NA
  • 标准化时必须用训练集的均值和标准差处理测试集,避免数据泄露

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 01:57:19