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 intodata.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"