2016-01-03 11 views
5

は、様々な1行のXTSのオブジェクトを考える:xtsオブジェクトをわずかに異なる列にマージするにはどうすればよいですか?

z1 = xts(t(c("9902"=0,"9903"=0,"9904"=0,"9905"=2,"9906"=2)),as.Date("2015-01-01")) 
z2 = xts(t(c("9902"=3,"9903"=4,"9905"=6,"9906"=5,"9908"=8)),as.Date("2015-01-02")) 
z3 = xts(t(c("9901"=1,"9903"=3,"9905"=5,"9906"=6,"9907"=7,"9909"=9)),as.Date("2015-01-03")) 

私は、単一のXTSのオブジェクトにマージします。しかしcbind(z1,z2,z3)ができます:私は何を期待一方

  X9902 X9903 X9904 X9905 X9906 X9902.1 X9903.1 X9905.1 X9906.1 X9908 X9901 X9903.2 X9905.2 X9906.2 X9907 X9909 
2015-01-01  0  0  0  2  2  NA  NA  NA  NA NA NA  NA  NA  NA NA NA 
2015-01-02 NA NA NA NA NA  3  4  6  5  8 NA  NA  NA  NA NA NA 
2015-01-03 NA NA NA NA NA  NA  NA  NA  NA NA  1  3  5  6  7  9 

は次のとおりです。

  9901 9902 9903 9904 9905 9906 9907 9908 9909 
2015-01-01 0 0 0 0 2 2 0 0 0 
2015-01-02 0 3 4 0 6 5 0 8 0 
2015-01-03 1 0 3 0 5 6 7 0 9 

(私はNASがすなわちcbind(z1,z2,z3,fill=0)fill=0を与えることでゼロに変更を取得することができます。)

rbind(z1,z2,z3)が行と文句を言い列の数が異なります。しかし、私は、もしこれが良いアプローチであることを失われた列が各xtsオブジェクトに事前に追加されていれば、私は信じていますか?

実際のデータには、行数が1000、列数が数百(一度結合された)のデータが含まれている可能性があります。

+0

'merge.xts'と' merge.zoo'あなたは 'merge'(または' cbind')を使用して、目的の結果を得ることができないので、唯一の、インデックスでマージします。ですから、 'rbind'が必要なように見えますが、あなたが言うように、すべてのオブジェクトが同じ順序で同じ数の列を必要とします。 –

答えて

4
に変換します

私のコメントで述べたように、merge.xts(とmerge.zoo)はインデックスのみでマージするので、merge(またはcbind)を使って望みの結果を得ることができません。だからあなたはrbindが必要ですが、(あなたが言うように)すべてのオブジェクトが同じ順序で同じ数の列を持つことが必要になります。

オブジェクトを処理するのに役立つ2つの関数を作成しましたので、希望の結果を作成するにはrbindを使用できます。

# put all xts objects in a list for easier processing 
x <- list(z1, z2, z3) 

# function to create template xts object 
template <- function(xlist) { 
    # find set of unique column names from all objects 
    cn <- unique(unlist(lapply(xlist, colnames))) 
    # create template xts object 
    # using a date that doesn't occur in the actual data 
    minIndex <- do.call(min, lapply(xlist, function(x) index(x[1L,]))) 
    # template object 
    xts(matrix(0,1,length(cn)), minIndex-1, dimnames=list(NULL, sort(cn))) 
} 

# function to apply to each xts object 
proc <- function(x, template) { 
    # columns we need to add 
    neededCols <- !(colnames(template) %in% colnames(x)) 
    # merge this object with template object, filling w/zeros 
    out <- merge(x, template[,neededCols], fill=0) 
    # reorder columns (NB: merge.xts always uses make.names) 
    # and remove first row (from template) 
    out <- out[-1L,make.names(colnames(template))] 
    # set column names back to desired values 
    # (using attr<- because dimnames<-.xts copies) 
    attr(out, "dimnames") <- list(NULL, colnames(template)) 
    # return object 
    out 
} 
(res <- do.call(rbind, lapply(x, proc, template=template(x)))) 
#   9901 9902 9903 9904 9905 9906 9907 9908 9909 
# 2015-01-01 0 0 0 0 2 2 0 0 0 
# 2015-01-02 0 3 4 0 6 5 0 8 0 
# 2015-01-03 1 0 3 0 5 6 7 0 9 
+0

ありがとうございます。私はこれと一緒に行くと思う。あなたは、それぞれのxtsオブジェクトを再作成してrbindを呼び出すのと比較して、1つの大きな空の行列を前面に出し、それをコピーするパフォーマンスに大きな違いがあると思いますか? (Rの行列は列順に並べられているので、とにかくrbindはそのようなコピーを行う必要があると思います) –

+1

@DarrenCook:私の頭の上から外れません。それは速いかもしれませんが、私はいずれかの方法で検証するためにプロファイルする必要があります。 'rbind'はそのようなコピーを行いますが、' memcopy'を使うことができます。通常はR関数を呼び出すよりも高速です。 –

1
library(xts) 
library(plyr) 

z1df <- as.data.frame(z1) 
z2df <- as.data.frame(z2) 
z3df <- as.data.frame(z3) 

res <- rbind.fill(z1df, z2df, z3df) 
res[is.na(res)] <- 0 
res 

# 9902 9903 9904 9905 9906 9908 9901 9907 9909 
#1 0 0 0 2 2 0 0 0 0 
#2 3 4 0 6 5 8 0 0 0 
#3 0 3 0 5 6 0 1 7 9 

これは

combining two data frames of different lengths

次のstackoverflowポストに似ては、日付列

res$Date <- c("2015-01-01", "2015-01-02", "2015-01-03") # the appropriate values 
res$Date <- as.Date(res$Date) 

が含まれており、XTSオブジェクト

xts(res[,-10], order.by=res[,10]) 
+2

'rbind.fill'はxtsにありません。あなたの結果はxtsオブジェクトでもありません。 –

+0

@JoshuaUlrichありがとうございました。 – steveb

+0

更新されたソリューションは、各オブジェクトの時刻が連続していて重複していないと仮定しています。実際のデータに適用すると、各行に間違った日付が割り当てられる可能性があります。 –

関連する問題