2016-01-03 23 views
5

Với khác nhau một hàng XTS đối tượng:Làm cách nào để hợp nhất các đối tượng xts với các cột hơi khác nhau?

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")) 

Tôi muốn kết hợp chúng thành một đối tượng XTS duy nhất. Nhưng cbind(z1,z2,z3) cho:

  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 

Trong khi những gì tôi mong đợi là:

  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 

(. Tôi có thể lấy NAS đổi thành zero với cho fill=0, tức là cbind(z1,z2,z3,fill=0))

rbind(z1,z2,z3) phàn nàn rằng các hàng có số cột khác nhau. Nhưng, tôi tin rằng nếu các cột bị thiếu được thêm vào từng đối tượng xts trước thì đây có phải là một cách tiếp cận tốt không?

Dữ liệu thực có thể có 1000 hàng và một vài trăm cột (khi đã được hợp nhất), vì vậy tôi đã có một mắt về hiệu quả.

+0

'merge.xts' và' merge.zoo' chỉ hợp nhất theo chỉ mục, vì vậy bạn không thể có được kết quả mong muốn bằng cách sử dụng 'hợp nhất' (hoặc' cbind'). Vì vậy, có vẻ như bạn cần 'rbind', nhưng (như bạn nói) nó sẽ yêu cầu tất cả các đối tượng có cùng số cột trong cùng một thứ tự. –

Trả lời

4

Như tôi đã đề cập trong nhận xét của tôi, merge.xts (và merge.zoo) chỉ hợp nhất theo chỉ mục, do đó bạn không thể có được kết quả mong muốn của mình bằng cách sử dụng merge (hoặc cbind). Vì vậy, có vẻ như bạn cần rbind, nhưng (như bạn nói), nó sẽ yêu cầu tất cả các đối tượng có cùng số cột trong cùng một thứ tự.

Tôi đã tạo hai chức năng bên dưới để giúp xử lý các đối tượng để bạn có thể rbind tạo các kết quả mong muốn của mình.

# 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

Cảm ơn; Tôi nghĩ rằng tôi sẽ đi với điều này. Bạn có nghĩ rằng sẽ có một sự khác biệt đáng kể trong hiệu suất để làm cho một ma trận trống khổng lồ lên phía trước, và sao chép vào đó, so với tái tạo từng đối tượng xts, sau đó gọi rbind? (Vì ma trận trong R là thứ tự cột lớn, tôi cho rằng rbind cần phải thực hiện loại bản sao đó?) –

+1

@DarrenCook: Không rời khỏi đỉnh đầu của tôi. Nó có thể nhanh hơn, nhưng tôi phải có hồ sơ để xác minh một trong hai cách. 'rbind' không thực hiện loại bản sao đó, nhưng nó có thể sử dụng' memcopy', thường nhanh hơn gọi hàm 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 

này cũng tương tự như các bài stackoverflow sau

combining two data frames of different lengths

Bao gồm cột ngày

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

Và chuyển đổi cho đối tượng XTS

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

'rbind.fill' không có trong xts. Kết quả của bạn cũng không phải là một đối tượng xts. –

+0

@JoshuaUlrich Cảm ơn. – steveb

+0

Giải pháp cập nhật giả định thời gian trong mỗi đối tượng là tuần tự và không trùng lặp, có khả năng không phải như vậy. Áp dụng cho dữ liệu thực tế, có khả năng sẽ chỉ định ngày sai cho mỗi hàng. –

Các vấn đề liên quan