2016-12-07 4 views
3

xtsオブジェクトxを迅速かつ効率的に分割してマージするには、xで参照されるものよりも大きなリストを使用しますか?すべての要因(不足している要素を含む)を使用して分割されたxtsのリストをマージする

この単純な例では、因子の完全なリスト(ゼロで埋められています)は生成されません。

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 

のようにダミーの値を削除し、その後、その後、分割され、マージ、すべてのグループに関連付けられたダミーの値を追加することですsplitおよびmerge

しかし、これらのソリューションは不必要に大きくなるようです。助言がありますか? split(または他の機能)とそのパラメータを利用するより良い方法はありますか?

答えて

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

ここでは、「非整理的」解決策があります。 :)

# 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))]