Home > Enterprise >  Converting Multiple existing xts objects to multiple data.frames
Converting Multiple existing xts objects to multiple data.frames

Time:09-21

There is already a thread asking how to convert multiple xts objects into as many data.frames here. Unfortunately, the solutions show how to do it for data that is being downloaded in .GlobalEnv. Moreover, the first answer of mentioned thread suggests to create a new environment, download the objects into it, and transform everything inside with the following code: stocks <- eapply(dataEnv, as.data.frame).

However, this creates a large list stored in the variable stocks, whereas I need the objects to remain discrete. Even when I run the code without generating a list (i.e., by just applying eapply(dataEnv, as.data.frame)), nothing happens. This has been documented here. In order to update the original object, the answer to this question was to use a code that looks like this: NKLA <- fortify.zoo(NKLA). This solution, which by the way works, is ok for a few objects that can be done manually and I need to automatise the process.

In my case, the objects are already downloaded and some of the them are data.frames, some are xts objects, and there might even be other objects.

What I need is to find the xts objects and transform them into data.frames.

In order to find the xts objects, I use the following code: xtsObjects <- which(unlist(eapply(.GlobalEnv, is.xts))), but applying xtsObjects <- fortify.zoo(xtsObjects) only creates yet another object called xtsObjects that contains, for example, 2 obs. of 2 variables (because there are 2 xts objects in the environment).

For example, the following code (which should be reproducible) does not change the discrete xts objects into discrete data.frames:

library(quantmod)
library(zoo)
tickers <- c("TSLA", "RMO", "TSM", "PDD")
getSymbols.yahoo(tickers, auto.assign = TRUE, env = globalenv())

xtsObjects <- which(unlist(eapply(.GlobalEnv, is.xts)))

# This does not do anything:
for (i in 1:length(xtsObjects)) fortify.zoo(xtsObjects[i])

My question:

  • What loop (or any code) could I use in order to simultaneously update the original already loaded/existing xts objects into data.frame objects?

System used:

  • R version: 4.1.1 (2021-08-10)
  • RStudio version: 1.4.1717
  • OS: macOS Catalina version 10.15.7

CodePudding user response:

By wrapping with which, it just returns the position with the names of the objects and not the actual objects. We may need to get the value of the objects with the names from that 'xtsObjects' output (mget - returns the values of multiple objects in a list, then loop over the list with map and convert to data.frame)

library(dplyr)
library(purrr)
out <- mget(names(xtsObjects)) %>% 
      map(fortify.zoo)

-output

> str(out)
List of 4
 $ PDD :'data.frame':   793 obs. of  7 variables:
  ..$ Index       : Date[1:793], format: "2018-07-26" "2018-07-27" "2018-07-30" "2018-07-31" ...
  ..$ PDD.Open    : num [1:793] 26.5 27.5 23.3 22.2 19.4 ...
  ..$ PDD.High    : num [1:793] 27.5 27.5 23.9 22.7 21.4 ...
  ..$ PDD.Low     : num [1:793] 25 23.2 21.9 19.6 18.6 ...
  ..$ PDD.Close   : num [1:793] 26.7 24.6 22.5 22.6 20.3 ...
  ..$ PDD.Volume  : num [1:793] 43213200 19923300 13967700 13709600 19339000 ...
  ..$ PDD.Adjusted: num [1:793] 26.7 24.6 22.5 22.6 20.3 ...
 $ RMO :'data.frame':   623 obs. of  7 variables:
  ..$ Index       : Date[1:623], format: "2019-04-01" "2019-04-02" "2019-04-03" "2019-04-04" ...
  ..$ RMO.Open    : num [1:623] 9.8 9.75 9.75 9.76 9.78 9.76 9.76 9.77 9.74 9.74 ...
  ..$ RMO.High    : num [1:623] 9.8 9.75 9.75 9.76 9.78 9.76 9.76 9.77 9.74 9.74 ...
  ..$ RMO.Low     : num [1:623] 9.75 9.75 9.75 9.76 9.75 9.76 9.76 9.77 9.74 9.74 ...
  ..$ RMO.Close   : num [1:623] 9.75 9.75 9.75 9.76 9.75 9.76 9.76 9.77 9.74 9.74 ...
  ..$ RMO.Volume  : num [1:623] 161000 11000 0 1000 100600 ...
  ..$ RMO.Adjusted: num [1:623] 9.75 9.75 9.75 9.76 9.75 9.76 9.76 9.77 9.74 9.74 ...
 $ TSLA:'data.frame':   2826 obs. of  7 variables:
  ..$ Index        : Date[1:2826], format: "2010-06-29" "2010-06-30" "2010-07-01" "2010-07-02" ...
  ..$ TSLA.Open    : num [1:2826] 3.8 5.16 5 4.6 4 ...
  ..$ TSLA.High    : num [1:2826] 5 6.08 5.18 4.62 4 ...
  ..$ TSLA.Low     : num [1:2826] 3.51 4.66 4.05 3.74 3.17 ...
  ..$ TSLA.Close   : num [1:2826] 4.78 4.77 4.39 3.84 3.22 ...
  ..$ TSLA.Volume  : num [1:2826] 93831500 85935500 41094000 25699000 34334500 ...
  ..$ TSLA.Adjusted: num [1:2826] 4.78 4.77 4.39 3.84 3.22 ...
 $ TSM :'data.frame':   3704 obs. of  7 variables:
  ..$ Index       : Date[1:3704], format: "2007-01-03" "2007-01-04" "2007-01-05" "2007-01-08" ...
  ..$ TSM.Open    : num [1:3704] 11.1 10.9 10.8 10.6 10.8 ...
  ..$ TSM.High    : num [1:3704] 11.1 11 10.8 10.8 10.8 ...
  ..$ TSM.Low     : num [1:3704] 10.8 10.7 10.5 10.6 10.5 ...
  ..$ TSM.Close   : num [1:3704] 10.9 10.9 10.6 10.7 10.6 ...
  ..$ TSM.Volume  : num [1:3704] 12438784 17678653 12691240 5477350 7396096 ...
  ..$ TSM.Adjusted: num [1:3704] 6.38 6.38 6.21 6.25 6.17 ...

Regarding the for loop doesn't do anything issue, 1) it is simply trying to do fortify.zoo on the object names and not on the values, 2) even if it is the value on which fortify.zoo is applied, it should be assigned back to the original object i.e. if we want to update the original object names, use assign

for (i in seq_along(xtsObjects)) {
     assign(names(xtsObjects[i]), fortify.zoo(get(names(xtsObjects[i]))))
}

CodePudding user response:

Use the names(which()) and then lapply.

xtsObjects <- names(which(unlist(eapply(.GlobalEnv, is.xts))))
res <- lapply(mget(xtsObjects), fortify.zoo)
head(res[[1]])
#        Index RMO.Open RMO.High RMO.Low RMO.Close RMO.Volume RMO.Adjusted
# 1 2019-04-01     9.80     9.80    9.75      9.75     161000         9.75
# 2 2019-04-02     9.75     9.75    9.75      9.75      11000         9.75
# 3 2019-04-03     9.75     9.75    9.75      9.75          0         9.75
# 4 2019-04-04     9.76     9.76    9.76      9.76       1000         9.76
# 5 2019-04-05     9.78     9.78    9.75      9.75     100600         9.75
# 6 2019-04-08     9.76     9.76    9.76      9.76      20500         9.76

length(res)
# [1] 4
names(res)
# [1] "RMO"  "TSM"  "TSLA" "PDD" 

To get the resulting data frames directly into the workspace use list2env.

list2env(lapply(mget(xtsObjects), fortify.zoo))
ls()  ## list objects currently in workspace
# [1] "PDD"        "RMO"        "tickers"    "TSLA"       "TSM"        "xtsObjects"
  • Related