Stata 做得好的一件事是它构造新变量的方式(见下面的例子)。如何在 R 中做到这一点?
foreach i in A B C D {
forval n=1990/2000 {
local m = 'n'-1
# create new columns from existing ones on-the-fly
generate pop'i''n' = pop'i''m' * (1 + trend'n')
}
}
不要在 R 中这样做。它混乱的原因是因为它的代码很丑。用程序名称构造大量变量是一件坏事。名字就是名字。它们没有结构,所以不要试图强加给它们。体面的编程语言有这样的结构——垃圾编程语言有附加的“宏”特性,最终会出现这种通过将字符串粘贴在一起来构造变量名的可怕模式。这是 1970 年代的一种做法,现在应该已经消失了。不要成为编程恐龙。
例如,你怎么知道你有多少个 popXXXX 变量?你怎么知道你是否有完整的 pop1990 到 pop2000 序列?如果您想将变量保存到文件中以提供给某人怎么办。呸呸呸。
使用语言为您提供的数据结构。在这种情况下可能是一个列表。
Spacedman 和 Joshua 都有非常有效的观点。由于 Stata 在任何给定时间在内存中只有一个数据集,我建议将变量添加到数据框(这也是一种列表)而不是全局环境(见下文)。
但老实说,这样做的更多 R-ish 方法是保留您的因子因子而不是变量名称。
我做了一些数据,因为我相信它现在在你的 R 版本中(至少,我希望如此......)
Data <- data.frame(
popA1989 = 1:10,
popB1989 = 10:1,
popC1989 = 11:20,
popD1989 = 20:11
)
Trend <- replicate(11,runif(10,-0.1,0.1))
然后,您可以使用该stack()
函数获取具有因子pop
和数值变量的数据框year
newData <- stack(Data)
newData$pop <- substr(newData$ind,4,4)
newData$year <- as.numeric(substr(newData$ind,5,8))
newData$ind <- NULL
填充数据框非常容易:
for(i in 1:11){
tmp <- newData[newData$year==(1988+i),]
newData <- rbind(newData,
data.frame( values = tmp$values*Trend[,i],
pop = tmp$pop,
year = tmp$year+1
)
)
}
在这种格式中,您会发现大多数 R 命令(几年的选择、单个种群的选择、其中一个或两个的建模效果……)以后执行起来要容易得多。
如果你坚持,你仍然可以创建一个宽格式unstack()
unstack(newData,values~paste("pop",pop,year,sep=""))
改编约书亚的答案以将列添加到数据框:
for(L in LETTERS[1:4]) {
for(i in 1990:2000) {
new <- paste("pop",L,i,sep="") # create name for new variable
old <- get(paste("pop",L,i-1,sep=""),Data) # get old variable
trend <- Trend[,i-1989] # get trend variable
Data <- within(Data,assign(new, old*(1+trend)))
}
}
假设popA1989
, popB1989
, popC1989
,popD1989
已经存在于您的全局环境中,下面的代码应该可以工作。当然还有更多“类似 R”的方法可以做到这一点,但我想给你一些类似于你的 Stata 代码的东西。
for(L in LETTERS[1:4]) {
for(i in 1990:2000) {
new <- paste("pop",L,i,sep="") # create name for new variable
old <- get(paste("pop",L,i-1,sep="")) # get old variable
trend <- get(paste("trend",i,sep="")) # get trend variable
assign(new, old*(1+trend))
}
}
假设您有向量中的人口数据pop1989
和趋势数据trend
。
require(stringr)# because str_c has better default for sep parameter
dta <- kronecker(pop1989,cumprod(1+trend))
names(dta) <- kronecker(str_c("pop",LETTERS[1:4]),1990:2000,str_c)