Как переписать этот код Stata в R? - PullRequest
9 голосов
/ 17 февраля 2011

Одна из вещей, которые 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 ]

15 голосов
/ 17 февраля 2011

НЕ делайте этого в R. Причина, по которой он запутан, в том, что его Гадкий код. Создание большого количества переменных с программными именами - ПЛОХАЯ вещь. Имена есть имена. У них нет структуры, поэтому не пытайтесь навязать им одну. Достойные языки программирования имеют структуры для этого - мусорные языки программирования имеют встроенные функции «Макро» и в итоге получают этот ужасный шаблон построения имен переменных путем вставки строк вместе. Это практика 1970-х годов, которая к настоящему времени должна была исчезнуть. Не будь программистом динозавром.

Например, как узнать, сколько у вас переменных popXXXX? Как узнать, есть ли у вас полная последовательность от pop1990 до pop2000? Что делать, если вы хотите сохранить переменные в файл, чтобы дать кому-то. Фу, гадо, гадость.

Используйте структуру данных, которую вам дает язык. В этом случае, вероятно, список.

9 голосов
/ 17 февраля 2011

И у Спейсмена, и у Джошуа очень хорошие очки.Поскольку в любой момент времени Stata имеет только один набор данных в памяти, я бы предложил добавить переменные в фрейм данных (который также является своего рода списком), а не в глобальную среду (см. Ниже).

Но, честно говоря, более R-ишный способ сделать это - сохранить ваши факторы факторов вместо имен переменных.

Я делаю некоторые данные, так как считаю, что они есть в вашей версии 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)))
  }
}
3 голосов
/ 17 февраля 2011

Предполагая, что 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))
  }
}
1 голос
/ 20 февраля 2011

Если у вас есть данные о населении в векторе 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)
...