简体   繁体   English

R:生成变量名,在函数列表中求值一个函数,然后在循环内将这些值分配给生成的变量名

[英]R: Generate variable names, evaluate a function within a list of functions, and assign those values to the generated variable names within a loop

Please excuse me if there are already answers to this, but I can't quite figure it out from the archives. 如果对此已经有答案,请原谅,但是我不能从档案中找出答案。

I have generated a list of very similar functions via a for-loop in R: 我已经通过R中的for循环生成了非常相似的函数列表:

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

I am now interested in applying this function to generate values for variables that have yet to be created in the dataframe. 我现在有兴趣应用此函数为尚未在数据框中创建的变量生成值。 I want to do this using a loop or similar since the process is identical, though the specific values change, over the 40 iterations. 我想使用循环或类似方法来执行此操作,因为在40次迭代中,尽管特定值有所变化,但过程是相同的。 The code would look something like: 代码看起来像:

#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="")))
}

I have played around with mget for the var_names segment, but that doesn't seem to work and the eval segment is also not working (ie, not assigning the values determined by the function (which works fine) to the appropriate dataframe column. 我为var_names段使用了mget,但似乎不起作用,并且eval段也无法正常工作(即,未将函数确定的值(可以正常工作)分配给适当的dataframe列。

Again, apologies if this has already been answered and thanks in advance for your help. 再次致歉,如果已回答您,请在此先感谢您的帮助。

How about adding an extra argument to your function? 如何在函数中添加额外的参数?

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

This would allow you to do the replacement quite a lot easier, using the fact that a dataframe is a special kind of list. 使用数据框是一种特殊的列表这一事实,这将使您的替换工作容易得多。 That was your original problem I believe : 我相信那是您最初的问题:

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

}

Check also the help pages ?which and ?Extract 还要查看帮助页面?which?Extract

Now without reproducible example (see How to make a great R reproducible example? ), it's hard to guess what you want to do and how to do this more economical. 现在没有可重现的示例(请参见如何制作出色的R可重现示例? ),很难猜测您想要做什么以及如何更经济地进行操作。 You're still using a lot of calculation time. 您仍在使用大量计算时间。 The following function might do what you want : 以下功能可能会满足您的要求:

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

which allows you to simply do 这使您只需

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

to get the desired result. 获得理想的结果。 This is given that the names of your variables are yearenter , adoptyear and yearleave . 假定变量的名称为yearenter ,采用adoptyearyearleave As far as I can see, you have to change yearenter to intoobsyear in the function, but that's a detail. 据我所知,您必须在函数yearenter intoobsyear更改为intoobsyear ,但这很详细。

Learning to use indices will save you a lot of frustration. 学习使用索引将为您节省很多挫败感。 And please, never ever make 40 identical functions again if adding one argument will do. 而且,请不要再添加40个相同的函数(如果添加一个参数)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM