Loop over string variables in R

Podczas programowania w Stata często używam indeksu pętli w programowaniu. Na przykład, zapętlę listę zmiennych nominalprice i realprice:

local list = "nominalprice realprice"
foreach i of local list {
  summarize `i'
  twoway (scatter `i' time)
  graph export "C:\TimePlot-`i'.png"
}

Wykreśli szereg czasowy cen nominalnych i rzeczywistych i wyeksportuje jeden Wykres o nazwie TimePlot-nominalprice.png i inny o nazwie TimePlot-realprice.png.

W R metoda, którą wymyśliłem, aby zrobić to samo, to:

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() 
}

Ten kod R wygląda nieintuitywnie i nie znalazłem jeszcze dobrego sposobu na takie rzeczy w r. Może po prostu nie myślę o problemie w odpowiedni sposób? Czy możesz zasugerować lepszy sposób pętli za pomocą ciągów?

Author: Metrics, 2009-11-02

4 answers

Jak już zauważyli inni, byłoby łatwiej, gdybyś miał ramkę danych z kolumnami o nazwach nominalprice i realprice. Jeśli nie, zawsze możesz użyć get. Nie powinieneś w ogóle tu być.

clist <- c("nominalprice", "realprice")
for (i in clist) {
   png(paste("c:/TimePlot-",i,".png"), sep="")
   plot(time, get(i))
   dev.off() 
}
 19
Author: Jonathan Chang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 20:48:40

Jeśli twoim głównym problemem jest potrzeba wpisania eval(parse (text=i)) zamiast `i" , możesz utworzyć prostszą w użyciu funkcję do oceny wyrażeń z łańcuchów:

e = function(expr) eval(parse(text=expr))

Wtedy przykład R można uprościć do:

clist <- c("nominalprice", "realprice")
for (i in clist) {
  png(paste("c:/TimePlot-", i, ".png", sep=""))
  plot(time, e(i))
  dev.off() 
}
 2
Author: Tuure Laurinolli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 20:37:48

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)
 1
Author: Eduardo Leoni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 20:48:10

Nie widzę, co jest szczególnie złego w Twoim oryginalnym rozwiązaniu, poza tym, że nie wiem, dlaczego używasz funkcji eval (). Nie wydaje mi się to konieczne.

Można również użyć funkcji apply, np. lapply. Oto działający przykład. Stworzyłem atrapy danych jako zoo() szereg czasowy (nie jest to konieczne, ale skoro i tak pracujesz z danymi szeregów czasowych):

# 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)
 1
Author: Shane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-02 20:57:35