简体   繁体   中英

Update an xts time series object with data from another xts object

I'm looking for a simpler way to update an xts time series object using data in another xts object. Data for overlapping time periods & dimensions should be updated, additional time periods should be added, and missing series dimensions should be added as needed. Currently I'm using a combination of merge, subset, and assignment. Is there a way to do this in fewer steps?

Example

Two xts times series objects with one dimension in common (y) and two time periods in common (2018 Q2 and 2018 Q3).

library(xts)

t <- as.yearqtr(paste(2018, 1:4, sep = ":Q"), format = "%Y:Q%q")

short <- xts(
    matrix(1, ncol = 2, nrow = 2, dimnames = list(NULL, c("x", "y"))), 
    order.by = t[2:3]
)

long <- xts(
    matrix(0, ncol = 2, nrow = 4, dimnames = list(NULL, c("y", "z"))),
    order.by = t
)

short

        x y
2018 Q2 1 1
2018 Q3 1 1

long

        y z
2018 Q1 0 0
2018 Q2 0 0
2018 Q3 0 0
2018 Q4 0 0

Desired result for case 1: updating short with long

         x  y z
2018 Q1 NA  0 0
2018 Q2  1  0 0
2018 Q3  1  0 0
2018 Q4 NA  0 0

Desired result for case 2: updating long with short

         x  y z
2018 Q1 NA  0 0
2018 Q2  1  1 0
2018 Q3  1  1 0
2018 Q4 NA  0 0

Case 1

Merge for non-overlapping dimensions, then subset and assign for overlapping dimensions (as in: Updating an XTS object )

short2 <- short
for (j in setdiff(colnames(long), colnames(short2))) {
    short2 <- merge(short2, long[, j])
}
short3 <- short2
for (j in intersect(colnames(short3), colnames(long))) {
    short3[index(long), j] <- long[, j]
}
short3

         x y z
2018 Q1 NA 0 0
2018 Q2  1 0 0
2018 Q3  1 0 0
2018 Q4 NA 0 0

Case 2

Same approach: merge for non-overlapping series dimensions, then subset and assign for overlapping dimensions

long2 <- long
for (j in setdiff(colnames(short), colnames(long2))) {
    long2 <- merge(long2, short[, j])
}
long3 <- long2
for (j in intersect(colnames(short), colnames(long3))) {
    long3[index(short), j] <- short[, j]
}
long3

        y z  x
2018 Q1 0 0 NA
2018 Q2 1 0  1
2018 Q3 1 0  1
2018 Q4 0 0 NA

Is there anything simpler than this two-step process? Perhaps a function or option from another package.

There's no way in R to merge while assigning priorities to columns that share the same name. I had a similar question a while ago. R must produce unique column names by default. You can directly assign columns a common name afterward using setNames , but R will always assign unique names (see ?make.names for some explanation). This is not recommended though as it will make actions after that much more complicated.

Manipulating ts and xts objects is also complicated. It can be done, but isn't really worth the time. It's best to convert to data.frame or tibble and do your business in those formats, then convert back.

The following is a tidyverse solution and also uses the timetk package.

library(xts)
library(timetk)
library(dplyr)

xts::merge.xts(long, short) %>% #merge xts objects using merge.xts
  timetk::tk_tbl() %>% #convert xts object to tibble
  dplyr::mutate(y = dplyr::coalesce(y.1, y)) %>% #replace y with coalesced y & y.1
  dplyr::select(-y.1) %>% #deselect y.1
  timetk::tk_xts(silent = T) #convert back to xts

        y z  x
2018 Q1 0 0 NA
2018 Q2 1 0  1
2018 Q3 1 0  1
2018 Q4 0 0 NA

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM