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

为多股票历史价格数据框添加RSI列时遇数据匹配错误求助

问题:多股票数据框添加RSI列时出现长度不匹配错误

我使用BatchGetSymbols获取多只股票历史价格数据,通过TTR包计算RSI值后,无法将结果正确合并到原数据框中,出现长度不匹配的报错。

现有代码

library(BatchGetSymbols) 
library(TTR)

first.date <- Sys.Date()-101
last.date <- Sys.Date()
l.out <- BatchGetSymbols(tickers = tickers_list,first.date = first.date,last.date = last.date, do.cache=FALSE)
my_data <- l.out$df.tickers
RSI <- by(my_data , my_data$ticker, function(sub) TTR::RSI(sub$price.close))

尝试合并时的错误

  1. 直接赋值:
my_data$RSI <- RSI

报错:

Error in set(x, j = name, value = value) : 
  Supplied 1617 items to be assigned to 113174 items of column 'RSI'. If you wish to 'recycle' the RHS please use rep() to make this intent clear to readers of your code.
  1. 使用do.call(rbind):
my_data$rsi <- do.call(rbind, RSI)

报错:

Error in set(x, j = name, value = value) : 
  Supplied 113190 items to be assigned to 113174 items of column 'rsi'. If you wish to 'recycle' the RHS please use rep() to make this intent clear to readers of your code.
In addition: Warning messages:
1: In (function (..., deparse.level = 1)  :
  number of columns of result is not a multiple of vector length (arg 1340)
2: In set(x, j = name, value = value) :
  70 column matrix RHS of := will be treated as one vector

解决方案

方案1:用dplyr分组计算(推荐)

直接在分组内计算RSI,避免先计算再合并的长度匹配问题:

library(dplyr)
library(BatchGetSymbols) 
library(TTR)

first.date <- Sys.Date()-101
last.date <- Sys.Date()
l.out <- BatchGetSymbols(tickers = tickers_list, first.date = first.date, last.date = last.date, do.cache=FALSE)
my_data <- l.out$df.tickers

# 按股票分组计算RSI并添加为新列
my_data <- my_data %>%
  group_by(ticker) %>%
  mutate(RSI = TTR::RSI(price.close)) %>%
  ungroup()

方案2:用data.table高效处理

针对大数据量场景,data.table的分组操作性能更优:

library(data.table)
library(BatchGetSymbols) 
library(TTR)

first.date <- Sys.Date()-101
last.date <- Sys.Date()
l.out <- BatchGetSymbols(tickers = tickers_list, first.date = first.date, last.date = last.date, do.cache=FALSE)
my_data <- as.data.table(l.out$df.tickers)

# 按ticker分组计算RSI
my_data[, RSI := TTR::RSI(price.close), by = ticker]

方案3:修复原代码的列表合并问题

如果坚持使用by()计算,需要将列表转为扁平向量后赋值,同时排查长度不匹配的分组:

# 将by返回的分组列表转为扁平向量
rsi_vector <- unlist(RSI, use.names = FALSE)

# 检查长度是否匹配,不匹配则定位问题股票
if(length(rsi_vector) == nrow(my_data)){
  my_data$RSI <- rsi_vector
} else {
  # 对比每个股票的RSI长度和原数据行数
  rsi_group_lengths <- sapply(RSI, length)
  data_group_lengths <- my_data %>% 
    group_by(ticker) %>% 
    summarise(n = n()) %>% 
    tibble::column_to_rownames("ticker") %>% 
    pull(n)
  
  mismatch_tickers <- names(which(rsi_group_lengths != data_group_lengths))
  cat("长度不匹配的股票:", paste(mismatch_tickers, collapse = ", "), "\n")
}

问题原因
  1. by()返回的是分组列表,直接赋值给数据框列时,R会将列表作为单个元素循环填充,导致长度不匹配。
  2. do.call(rbind, RSI)会把每个RSI向量转为矩阵的列,而非行,矩阵按列优先展开后长度与原数据不匹配。
  3. 部分股票的RSI长度与原数据分组行数不一致,大概率是因为对应股票的price.close存在NA值,或者BatchGetSymbols返回的该股票数据有异常行数。

内容的提问来源于stack exchange,提问作者Vasco de Gama

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:20:42