2009-11-02 25 views
12

Cuando programo en Stata, a menudo me encuentro utilizando el índice de bucle en la programación. Por ejemplo, voy a un bucle sobre una lista de las variables nominalprice y realprice:Bucle en variables de cadena en R

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

Esto trazar las series temporales de los precios nominales y reales y exportar un gráfico llamado TimePlot-nominalprice.png y otro llamado TimePlot- realprice.png.

En R el método que he llegado con hacer lo mismo sería:

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

Este código R parece poco intuitivo y desordenado a mí y no he encontrado una buena manera de hacer esto tipo de cosas en R todavía. Tal vez simplemente no estoy pensando en el problema de la manera correcta? ¿Puedes sugerir una mejor forma de hacer bucles usando cadenas?

Respuesta

16

Como otras personas han dado a entender, esto sería más fácil si has tenido una trama de datos con columnas llamadas nominalprice y realprice. Si no lo hace, siempre puede usar get. No debe necesitar parse en absoluto aquí.

clist <- c("nominalprice", "realprice") 
for (i in clist) { 
    png(paste("c:/TimePlot-",i,".png"), sep="") 
    plot(time, get(i)) 
    dev.off() 
} 
+0

Gracias Jonathon. Me gusta la opción get (i) e intentaré trabajar con eso. Los datos que estaba usando son datos ficticios, por lo que podrían estructurarse en un marco de datos. ¿Qué sería diferente si se usa un marco de datos? – aTron

+0

Porque entonces es fácil acceder por cadena. Supongamos que tiene un marco de datos 'df' con una columna llamada' nominalprice'. Luego puede escribir 'df [," nominalprice "]' para obtener esa columna. –

1

No veo qué está especialmente mal con su solución original, excepto que no sé por qué está utilizando la función eval(). Eso no me parece necesario.

También puede usar una función de aplicar, como aplicar. Aquí hay un ejemplo de trabajo. Creé datos ficticios como una serie de tiempo zoo() (esto no es necesario, pero ya que se trabaja con datos de series de tiempo de todos modos):

# 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) 
+0

En la función anterior, ¿a qué se refiere c.name? Intento entender cómo podría aplicar esta técnica a otras situaciones. – aTron

+0

c.nombre es un nombre de variable que estoy asignando a lo que get pasa por lapply (lapply, en esta instancia, es simplemente pasar cada elemento de ese vector, uno a la vez). Intente jugar con esto para ver cómo funciona: aplique (c (1,2,3), función (x) impresión (x)). También mira? Lapply. – Shane

2

Si el problema principal es la necesidad de escribir eval (análisis sintáctico (texto = i)) en lugar de `` i'`, se podría crear una funciones más simples de usar para evaluar expresiones de cadenas:

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

Entonces el ejemplo R podría simplificarse a:

clist <- c("nominalprice", "realprice") 
for (i in clist) { 
    png(paste("c:/TimePlot-", i, ".png", sep="")) 
    plot(time, e(i)) 
    dev.off() 
} 
+0

¡Gracias por su respuesta! Este es un consejo muy útil. Definitivamente simplificará mi codificación. – aTron

+0

Creo que debería usar get() como lo muestra Jonathan Chang en su lugar. –

1

Usando ggplot2 a nd remodelar:

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)