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')
}
}
答案 0 :(得分:15)
不要在R中这样做。它混乱的原因是它的UGLY代码。使用程序化名称构造大量变量是一件坏事。名字是名字。它们没有结构,所以不要试图强加它们。体面的编程语言有这样的结构 - 垃圾编程语言已经加入了'宏'功能,并最终通过将字符串粘贴在一起构建变量名称这种糟糕的模式。这是20世纪70年代的一种做法,现在应该已经消亡。不要成为编程恐龙。
例如,您如何知道有多少popXXXX变量?你怎么知道pop1990到pop2000的完整序列?如果要将变量保存到文件以便提供给某人,该怎么办?哎呀,哎呀。
使用该语言提供的数据结构。在这种情况下可能是一个列表。
答案 1 :(得分:9)
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=""))
改编Joshua的答案,将列添加到数据框中:
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)))
}
}
答案 2 :(得分:3)
假设您的全球环境中已存在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))
}
}
答案 3 :(得分:1)
假设您在向量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)