使用apply处理多列xts对象时遇维度名匹配错误求助
解决xts时间序列切片时的维度不匹配错误
我碰到过类似的问题,其实根源出在apply的自动简化特性和空xts对象的处理上,咱们一步步拆解:
问题原因
当你的日期范围完全超出了ts的时间区间时,切片操作ts[paste0(...)])会返回0行的xts对象。而apply函数默认会尝试简化结果:如果某个切片是空的,它会把空xts转换成一个空向量,但其他有数据的切片是xts对象,这就导致列表里的元素类型/维度不一致,触发你看到的length of 'dimnames' 1 not equal to array extent错误。
看你的例子:
- 第一个
range.matrix的范围是2014-09-01/2017-04-30,但ts的时间只到2017-01-08,所以切片结果是空xts,apply处理时就会出错; - 第三个例子的两个范围都覆盖了
ts的部分时间,切片都有数据,所以不会触发错误。
解决方案
有两种简单的办法解决这个问题:
方法1:用lapply代替apply
lapply不会自动简化结果,会严格保留每个切片的xts类型(哪怕是空的),完美避免维度不匹配问题。修改代码如下:
library(xts) ts <- xts(cbind('a'= c(1,2,3,4,5,6,7,8),'b' =c(1,2,3,4,5,6,7,8),'c'= c(1,2,3,4,5,6,7,8)) ,order.by = as.Date(as.Date('2017-01-01'):(as.Date('2017-01-01')+7)) ) range.matrix <- matrix(c(16314,17286), ncol = 2,byrow = TRUE) # 用lapply遍历行索引 slice_list <- lapply(1:nrow(range.matrix), function(i) { r <- range.matrix[i, ] ts[paste0(as.Date(r[1]), '/', as.Date(r[2]))] }) # 查看结果,空切片会保留xts结构 str(slice_list)
方法2:在apply中强制保持xts结构
如果你一定要用apply,可以在切片后检查是否为空,若为空则返回一个和原ts列名一致的空xts,确保所有元素结构统一:
slice_list <- apply(range.matrix, 1, function(r) { slice <- ts[paste0(as.Date(r[1]), '/', as.Date(r[2]))] # 若切片为空,构造同结构的空xts if (nrow(slice) == 0) { xts(matrix(nrow=0, ncol=ncol(ts)), order.by=as.Date(character()), colnames=colnames(ts)) } else { slice } })
这两种方法都能解决单行矩阵的报错问题:单行场景下,lapply会返回一个包含单个元素的列表,而修改后的apply也会返回结构一致的结果。
内容的提问来源于stack exchange,提问作者lsmor
相关产品推荐
相关产品推荐

