在R中循环字符串变量

18

在Stata编程中,我经常会使用循环索引变量。例如,我将对名为nominalprice和realprice的变量列表进行循环:

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"
}

这将绘制名义价格和实际价格的时间序列,并导出一个名为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中做这种事情的好方法。也许我没有以正确的方式考虑这个问题?你能提供一种更好的使用字符串循环的方法吗?

4个回答

23

像其他人所说的那样,如果您有一个带有名为nominalpricerealprice列的数据框,则此操作会更容易。 如果没有,您始终可以使用get。在这里,您根本不需要使用parse

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

谢谢Jonathon。我喜欢get(i)选项,我会尝试使用它。我使用的数据是虚拟数据,因此可以在数据框中进行结构化。如果使用数据框,有什么不同? - aTron
因为这样可以通过字符串轻松访问。比如你有一个数据框df,其中有一列名为nominalprice。那么你只需写df[,"nominalprice"]就可以获取该列。 - Jonathan Chang

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

我认为你应该像Jonathan Chang所示那样使用get()。 - Tuure Laurinolli

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)

在上面的函数中,c.name 是指什么?我正在尝试理解如何将这种技术应用到其他情况。 - aTron
c.name是一个变量名,我正在将其分配给lapply传递的内容(在这种情况下,lapply只是逐个传递该向量的每个元素)。尝试使用以下代码进行测试:lapply(c(1,2,3), function(x) print(x))。同时查看?lapply。 - Shane

1
使用ggplot2和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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接