Как переписать этот код Stata в R?
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 ответа
НЕ ДЕЛАЙТЕ это в R. Причина, по которой он запутан, в том, что его Гадкий код. Создание большого количества переменных с программными именами - ПЛОХАЯ вещь. Имена есть имена. У них нет структуры, поэтому не пытайтесь навязать им одну. Достойные языки программирования имеют структуры для этого - мусорные языки программирования имеют встроенные функции "Макро" и в итоге получают этот ужасный шаблон построения имен переменных путем вставки строк вместе. Это практика 1970-х годов, которая к настоящему времени должна была исчезнуть. Не будь программистом динозавром.
Например, как вы узнаете, сколько у вас переменных popXXXX? Как узнать, есть ли у вас полная последовательность от pop1990 до pop2000? Что делать, если вы хотите сохранить переменные в файл, чтобы дать кому-то. Фу, гадо, гадость.
Используйте структуру данных, которую дает вам язык. В этом случае, вероятно, список.
И у Спейсмена, и у Джошуа есть очень веские очки. Поскольку Stata имеет только один набор данных в памяти в любой момент времени, я бы предложил добавить переменные в фрейм данных (который также является своего рода списком), а не в глобальную среду (см. Ниже).
Но, честно говоря, более надежный способ сделать это - сохранить факторы факторов вместо имен переменных.
Я делаю некоторые данные, так как считаю, что они есть в вашей версии 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)