2016-01-03 2 views
5

Учитывая различные однорядные 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 изменен на нулях с приданием fill=0, т.е. cbind(z1,z2,z3,fill=0))

rbind(z1,z2,z3) жалуется, что строки имеют разное количество столбцов. Но я считаю, что если бы отсутствующие столбцы были добавлены к каждому объекту xts заранее, это было бы хорошим подходом?

Реальные данные могут иметь 1000 строк и несколько сотен столбцов (после объединения), поэтому у меня есть один взгляд на эффективность.

+0

'' merge.xts' и merge.zoo' сливаются только по индексу, так что вы не можете получить желаемый результат с помощью 'merge' (или' cbind'). Таким образом, похоже, что вам нужно 'rbind', но (как вы говорите) это потребует, чтобы все объекты имели одинаковое количество столбцов в одном порядке. –

ответ

4

Как я упоминал в своем комментарии, merge.xtsmerge.zoo) объединяются только по индексу, поэтому вы не можете получить желаемый результат, используя merge (или cbind). Таким образом, похоже, что вам нужно rbind, но (как вы говорите) это потребует, чтобы все объекты имели одинаковое количество столбцов в одном порядке.

Я создал две функции ниже, чтобы помочь обработать объекты, чтобы вы могли 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

Thanks; Думаю, я пойду с этим. Как вы думаете, будет ли значительная разница в производительности, чтобы сделать одну огромную пустую матрицу впереди и скопировать туда, по сравнению с повторным созданием каждого объекта xts, а затем вызвать rbind? (Поскольку матрицы в 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 

Это аналогично следующему StackOverflow сообщению

combining two data frames of different lengths

Включить столбец даты

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

Обновленное решение предполагает, что времена в каждом объекте являются последовательными и неперекрывающимися, что, вероятно, не так. Применительно к фактическим данным, вероятно, они назначают неправильные даты для каждой строки. –

Смежные вопросы