如何在R中重写这个Stata代码?

时间:2011-02-17 02:25:49

标签: r stata

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

4 个答案:

答案 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)

假设您的全球环境中已存在popA1989popB1989popC1989popD1989,则以下代码应该有效。当然有更多“类似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)