R: Генерация имен переменных, оценка функции в списке функций и назначение этих значений сгенерированным именам переменных в цикле. - PullRequest
2 голосов
/ 30 октября 2011

Пожалуйста, извините, если на это уже есть ответы, но я не могу понять это из архивов.

Я сгенерировал список очень похожих функций через цикл for в R:

adoptint.fun=list()
    for(i in 1:40) {
    #function name for each column
    func.name <- paste('adoptint',i,sep='')
    #function
    func = paste('function(yearenter, adoptyear, yearleave) {ifelse(is.na(yearenter) | yearenter >', i+1905, ' | is.na(adoptyear) | yearleave > ', i+1905, ', NA, ifelse(yearenter <= ', i+1905, ' & adoptyear <= ', i+1905, ', 1, 0))}', sep='')
    adoptint.fun[[func.name]] = eval(parse(text=func))
}

Теперь я заинтересован в применении этой функции для генерации значений для переменных, которые еще не созданы в кадре данных. Я хочу сделать это, используя цикл или подобное, поскольку процесс идентичен, хотя конкретные значения меняются в течение 40 итераций. Код будет выглядеть примерно так:

#generate variables that will be inserted into dataframe, dfanal.reshape
var_names <- paste("dfanal.reshape$adopt", 1:40, sep="")

#run function i to obtain values for variable i, which should be appended to dataframe
for(i in 1:40){
    var_names[i] <- eval(parse(paste("adoptint.fun[[" ,i, "]](dfanal.reshape$intoobsyear,dfanal.reshape$adoptyear,dfanal.reshape$yearleave)", sep="")))
}

Я поэкспериментировал с mget для сегмента var_names, но это, похоже, не работает, и сегмент eval также не работает (т. Е. Не присваивает значения, определенные функцией (которые работают нормально), соответствующему фрейму данных столбец.

Снова извиняюсь, если на этот вопрос уже был дан ответ, и заранее благодарим за помощь.

1 Ответ

7 голосов
/ 30 октября 2011

Как насчет добавления дополнительного аргумента в вашу функцию?

func <- function(yearenter, adoptyear, yearleave,i) {
  ifelse(is.na(yearenter) | yearenter > i+1905 | is.na(adoptyear) | yearleave >  i+1905 , NA, 
         ifelse(yearenter <=  i+1905 & adoptyear <=  i+1905, 1, 0))
  }

Это позволит вам сделать замену намного проще, используя тот факт, что фрейм данных представляет собой особый вид списка.Я думаю, это была ваша первоначальная проблема:

for(i in 1:40){
  varname <- paste('adopt',i,sep='')
  dfanal.reshape[[varname]] <- 
    with(dfanal.reshape,
         func(intoobsyear,adoptyear,yearleave,i)
    )

}

Проверьте также страницы справки ?which и ?Extract

Теперь без воспроизводимого примера (см. Как сделать отличный RВоспроизводимый пример? ), трудно догадаться, что вы хотите сделать и как сделать это более экономичным.Вы все еще используете много времени для расчета.Следующая функция может делать то, что вы хотите:

func <- function(df,j){
  out <- matrix(0,nrow=nrow(df),ncol=j)
  attach(df)
  idna <- sapply(1:j,function(i)
    is.na(yearenter) | yearenter > i+1905 | is.na(adoptyear) | yearleave >  i+1905
    )
  out[idna] <- NA
  id1 <- sapply(1:j,function(i)
    yearenter <=  i+1905 & adoptyear <=  i+1905
    )
  out[id1] <- 1
  detach(df)
  colnames(out)<- paste('adopt',1:j,sep='')
  cbind(df,out)
}

, которая позволяет просто сделать

dfanal.reshape <- func(dfanal.reshape,40)

, чтобы получить желаемый результат.Это означает, что имена ваших переменных yearenter, adoptyear и yearleave.Насколько я понимаю, вы должны изменить yearenter на intoobsyear в функции, но это деталь.

Изучение использования индексов избавит вас от многих разочарований.И, пожалуйста, никогда больше не создавайте 40 одинаковых функций, если добавится один аргумент.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...