Loop over string variables in R
Solution 1
As other people have intimated, this would be easier if you had a dataframe with columns named nominalprice
and realprice
. If you do not, you could always use get
. You shouldn't need parse
at all here.
clist <- c("nominalprice", "realprice")
for (i in clist) {
png(paste("c:/TimePlot-",i,".png"), sep="")
plot(time, get(i))
dev.off()
}
Solution 2
If your main issue is the need to type eval(parse(text=i)) instead of ``i'`, you could create a simpler-to-use functions for evaluating expressions from strings:
e = function(expr) eval(parse(text=expr))
Then the R example could be simplified to:
clist <- c("nominalprice", "realprice")
for (i in clist) {
png(paste("c:/TimePlot-", i, ".png", sep=""))
plot(time, e(i))
dev.off()
}
Solution 3
I don't see what's especially wrong with your original solution, except that I don't know why you're using the eval() function. That doesn't seem necessary to me.
You can also use an apply function, such as lapply. Here's a working example. I created dummy data as a zoo()
time series (this isn't necessary, but since you're working with time series data anyway):
# x <- some time series data
time <- as.Date("2003-02-01") + c(1, 3, 7, 9, 14) - 1
x <- zoo(data.frame(nominalprice=rnorm(5),realprice=rnorm(5)), time)
lapply(c("nominalprice", "realprice"), function(c.name, x) {
png(paste("c:/TimePlot-", c.name, ".png", sep=""))
plot(x[,c.name], main=c.name)
dev.off()
}, x=x)
Solution 4
Using ggplot2 and reshape:
library(ggplot2)
library(reshape)
df <- data.frame(nominalprice=rexp(10), time=1:10)
df <- transform(df, realprice=nominalprice*runif(10,.9,1.1))
dfm <- melt(df, id.var=c("time"))
qplot(time, value, facets=~variable, data=dfm)
aTron
Economist working with Stata, R, and python on Ubuntu linux.
Updated on July 13, 2022Comments
-
aTron almost 2 years
When programming in Stata I often find myself using the loop index in the programming. For example, I'll loop over a list of the variables nominalprice and realprice:
local list = "nominalprice realprice" foreach i of local list { summarize `i' twoway (scatter `i' time) graph export "C:\TimePlot-`i'.png" }
This will plot the time series of nominal and real prices and export one graph called TimePlot-nominalprice.png and another called TimePlot-realprice.png.
In R the method I've come up with to do the same thing would be:
clist <- c("nominalprice", "realprice") for (i in clist) { e <- paste("png(\"c:/TimePlot-",i,".png\")", sep="") eval(parse(text=e)) plot(time, eval(parse(text=i))) dev.off() }
This R code looks unintuitive and messy to me and I haven't found a good way to do this sort of thing in R yet. Maybe I'm just not thinking about the problem the right way? Can you suggest a better way to loop using strings?
-
aTron over 14 yearsThanks Jonathon. I like the get(i) option and I'll try working with that. The data I was using is dummy data so could be structured in a dataframe. What would be different if using a dataframe?
-
aTron over 14 yearsIn the function above what does c.name refer to? I'm trying to understand how I could apply this technique to other situations.
-
Shane over 14 yearsc.name is a variable name that I'm assigning to what get's passed by lapply (lapply, in this instance, is just passing each element of that vector, one at a time). Try playing with this to see how it works: lapply(c(1,2,3), function(x) print(x)). Also look at ?lapply.
-
Tuure Laurinolli over 14 yearsI think you should use get() as shown by Jonathan Chang instead.
-
Jonathan Chang over 14 yearsBecause then it's easy to access by string. Say you have a data frame
df
with a column namednominalprice
. Then you can just writedf[,"nominalprice"]
to obtain that column.