在Stata编程时,我经常发现自己在编程中使用了循环索引。例如,我将循环遍历变量nominalprice和realprice的列表:
local list = "nominalprice realprice"
foreach i of local list {
summarize `i'
twoway (scatter `i' time)
graph export "C:\TimePlot-`i'.png"
}
这将绘制名义价格和实际价格的时间序列,并导出一个名为TimePlot-nominalprice.png的图表和另一个名为TimePlot-realprice.png的图表。
在R中,我想出的做同样事情的方法是:
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()
}
这个R代码对我来说看起来不直观和混乱,我还没有找到一种在R中做这种事情的好方法。也许我只是没有以正确的方式思考问题?你能建议一个更好的循环使用字符串的方法吗?
答案 0 :(得分:17)
正如其他人所暗示的那样,如果您的数据框中包含名为nominalprice
和realprice
的列,则会更容易。如果不这样做,您可以随时使用get
。你在这里根本不需要parse
。
clist <- c("nominalprice", "realprice")
for (i in clist) {
png(paste("c:/TimePlot-",i,".png"), sep="")
plot(time, get(i))
dev.off()
}
答案 1 :(得分:2)
如果您的主要问题是需要输入eval(parse(text = i))而不是“i”,那么您可以创建一个更简单的函数来评估字符串中的表达式:
e = function(expr) eval(parse(text=expr))
然后R示例可以简化为:
clist <- c("nominalprice", "realprice")
for (i in clist) {
png(paste("c:/TimePlot-", i, ".png", sep=""))
plot(time, e(i))
dev.off()
}
答案 2 :(得分:1)
我没有看到原始解决方案的特别之处,除了我不知道你为什么使用eval()函数。这对我来说似乎没有必要。
您还可以使用apply函数,例如lapply。这是一个有效的例子。我创建了虚拟数据作为zoo()
时间序列(这不是必需的,但是因为你正在使用时间序列数据):
# 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)
答案 3 :(得分:1)
使用ggplot2并重塑:
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)