使用所有因素(包括缺失因素)合并拆分的 xts 列表

Merge a list of splitted xts using all factors (including missing factors)

如何使用比 x 引用的因素更大的因素列表快速有效地拆分和合并 xts 对象 x

这个简单的例子没有产生完整的因素列表(用零填充)。

a = cbind(value = runif(2), group = c(1,3))
x = xts(a, Sys.Date() + 1:nrow(a))
do.call(merge, c(split(x$value, x$group), fill = 0))

             value.1   value.3
2016-12-08 0.3403723 0.0000000
2016-12-09 0.0000000 0.5247683

我的解决方法是附加与所有组关联的虚拟值,然后拆分和合并,然后删除虚拟值,如

all.groups = 1:5
x.all.groups = xts(cbind(value = 0, f = all.groups), Sys.Date()-1:length(all.groups)) 
x = rbind(x,x.all.groups)
as.xts(do.call(merge, c(split(x$value, x$group), fill = 0)))[!(index(x) %in% index(x.all.groups)),]

             value.1 value.2 value.3 value.4 value.5
2016-12-08 0.3455855       0 0.00000       0       0
2016-12-09 0.0000000       0 0.16545       0       0

另一种解决方法是在操作 splitmerge 之间附加缺失组的列表。

但是,这些解决方案似乎过于笨重。有什么建议么? 有没有更好的方法来利用 split(或其他一些函数)及其参数?

这是一个tidyverse解决方案。请注意,xts 对象是引擎盖下的矩阵,因此都是相同的类型。因此,首先转换为 data.frame 并为因子分配特定水平,然后在该因子上 spread

x %>% as.data.frame %>% 
  mutate(date = row.names(.),
         group = factor(.$group, levels = 1:5)) %>% 
  spread(group, value, fill = 0, drop = FALSE)


        date         1 2         3 4 5
1 2016-12-08 0.2238529 0 0.0000000 0 0
2 2016-12-09 0.0000000 0 0.6423199 0 0

这是另一种 "un-tidyverse" 解决方案。 :)

# sample data
set.seed(21)
x <- xts(cbind(value=runif(5), group=c(1,3,3,1,4)), Sys.Date()-c(2,2,3,1,1))
all.groups <- 1:5

# all unique index values
unique.index <- unique(index(x))
# template object with zero for every unique index value
xts.template <-  xts(rep(0, length(unique.index)), unique.index)
colnames(xts.template) <- "value"

# split existing data by group
s <- split(x$value, x$group)
# find completely missing groups
missing.groups <- all.groups[!(all.groups %in% names(s))]
# add missing groups to list as *named* elements, with all zero values
s[as.character(missing.groups)] <-
    replicate(length(missing.groups), xts.template, simplify=FALSE)

# call merge on all list elements, filling with zeros
result <- do.call(merge, c(s, fill = 0))

# order columns, if you want
result <- result[,sort(colnames(result))]