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

时间:2016-12-07 07:02:25

标签: r list merge split xts

如何使用比xts引用的更多因素更快速有效地拆分和合并x对象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(或其他一些功能)及其参数?

2 个答案:

答案 0 :(得分:1)

这是一个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

答案 1 :(得分:1)

这是另一种选择," 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))]