【问题标题】:paste variable names inside R function在 R 函数中粘贴变量名
【发布时间】:2012-04-17 19:06:37
【问题描述】:

借助flodelfound a way to replace numeric codes with value labels from a lookup table

虽然我很有野心,但我现在想把它放到一个函数中。另外,我有很多查找表需要快速查找我的数据,这样一个函数就会很方便。

但首先是一些示例数据,从数据帧开始,

df <- data.frame(id = c(1:6),
                 profession = c(1, 5, 4, NA, 0, 5))

df
#  id profession
#  1          1
#  2          5
#  3          4
#  4         NA
#  5          0
#  6          5

还有一个查找表,其中包含有关职业代码的人类可读信息,

profession.lookuptable <- c(Optometrists=1, Accountants=2, Veterinarians=3, 
                            `Financial analysts`=4,  Nurses=5)

flodel 给我看了how replace numeric codes with value labels from a lookup table。像这样,

match.idx <- match(df$profession, profession.lookuptable)
df$profession <- ifelse(is.na(match.idx), 
                 df$profession, names(profession.lookuptable)[match.idx])

df
#  id         profession
#  1        Optometrists
#  2              Nurses
#  3  Financial analysts
#  4                <NA>
#  5                   0
#  6              Nurses

我现在想把它放到一个函数中,我可以在其中声明数据框 df 和变量名称 profession,然后让函数处理其余的事情。

我这样定义我的函数,

ADDlookup <- function(orginalDF, orginalVAR) {
   DF.VAR <- paste(orginalDF, "$", orginalVAR, sep="")
   lookup.table <- paste(orginalVAR, ".lookuptable")
   match.idx <- match(DF.VAR, lookup.table)
   DF.VAR <- ifelse(is.na(match.idx), DF.VAR, names(lookup.table)[match.idx])
}

但显然这不起作用

ADDlookup(df, profession)

我得到了错误的混乱

Error in paste(orginalDF, "$", orginalVAR, sep = "") : 
  object 'profession' not found

现在,这就是我卡住的地方。

谁能告诉我需要阅读哪个手册页或者关于如何解决这个问题的友好提示?

感谢您的阅读。

【问题讨论】:

    标签: debugging r function


    【解决方案1】:

    这是因为您将profession 传递给ADDlookup 函数,但它还不存在。

    按照您编写函数的方式,您必须区分使用包含变量名称的字符向量变量本身

    例如,您的前几行 paste(originalDF,'$',originalVAR,sep='') 等似乎期望 originalDForiginalVAR字符串,而您将有 DF.VAR 作为 字符串'df$profession'。但是,当您执行 match 时,您似乎希望 DF.VAR 成为 变量 df$profession

    这就是我建议您绕过它的方法: - 传入originalDF 作为对象,即df - 传入originalVAR 作为字符串,即'profession'(它是一个列名,因此是一个字符串)

    然后,通过以下方式从数据框中检索originalVar 中包含的

    DF.VAR <- originalDF[,originalVAR] # e.g. df[,'profession']
    

    现在查找对象profession.lookuptable 的下一行有点棘手:构造字符串 'profession.lookuptable',然后要查找对象 em> 有那个名字。

    为此,您可以使用get (?get)。 get('df') 将返回 df 数据框:

    lookup.table <- get(paste(orginalVAR, "lookuptable",sep='.'))
    

    这将检索名为'profession.lookuptable' 的对象。它遵循与您直接输入profession.lookuptable 相同的规则,因此您必须确保该函数可以“看到”该对象(在您的情况下应该没问题)。

    接下来,您似乎想要返回 originalDF 数据框,其中 originalVAR 列已替换为查找值。

    我将修改 originalDF[,originalVAR] 列,将其替换为查找值:

    originalDF[,originalVAR] <- 
       ifelse(is.na(match.idx), DF.VAR, names(lookup.table)[match.idx])
    

    注意我们没有实际修改您作为参数传入ADDlookupdf 数据框; R 在函数内制作数据框的副本。所以,你原来的df 被保留了。

    最后,我们要返回数据框:

    return(originalDF)
    

    现在大家在一起:

    ADDlookup <- function(orginalDF, orginalVAR) {
       # retrieve the originalVAR column of originalDF
       DF.VAR <- originalDF[,originalVAR] 
       # find the variable called {originalVAR}.lookuptable
       lookup.table <- get(paste(originalVAR, "lookuptable",sep='.'))
       # look up the values
       match.idx <- match(DF.VAR, lookup.table)
       # replace the originalVAR column with the looked-up values
       originalDF[,originalVAR] <- 
           ifelse(is.na(match.idx), DF.VAR, names(lookup.table)[match.idx])
       # return the modified data frame
       return(originalDF)
    }
    

    现在来测试一下:

    > ADDlookup(df,'profession')
      id         profession
    1  1       Optometrists
    2  2             Nurses
    3  3 Financial analysts
    4  4               <NA>
    5  5                  0
    6  6             Nurses
    

    注意原来的df是未修改的;一般来说,R 函数不会修改传递给它们的参数。


    作为另一项改进——在调用ADDlookup 函数之前依赖已创建的professions.lookup 表通常有点危险。

    而不是整个lookup.table &lt;- get( 'profession.lookup' ) shebang(这取决于您是否在不同范围内有多个“profession.lookup”表),我强烈建议您只将查找表作为参数传递:

    ADDlookup <- function( originalDF, originalVAR, lookup.table )
    

    然后您可以避免整个 get(xxxx) 行(以及随之而来的所有相关范围界定问题)。

    然后你会通过以下方式调用函数:

    ADDlookup( df, 'profession', profession.lookup )
    

    【讨论】:

    • +1 好的,所以它并没有那个复杂得多,但我试图避免使用get
    • 是的,我也不喜欢使用get;我已经编辑了我的帖子来提及这一点。
    • @mathematical.coffee 哇哦,这是超级信息。感谢您花时间如此彻底地解释这一切。可能是我,但是当我运行你的代码时,我在运行最终函数Error in ADDlookup(df, "profession") : object 'originalDF' not found 时确实收到了一条错误消息。我早上再看一遍,我现在已经很晚了。再次感谢您抽出时间,我一定会重读您的帖子(几次)。谢谢!
    【解决方案2】:

    当然有更复杂的方法可以让它按照你最初设想的方式工作,但是简单地重新组织这个函数的工作方式会简单得多:

    ADDLookup <- function(originalDF,var,varLookup){
        match.idx <- match(originalDF[,var], varLookup)
        originalDF[,var] <- ifelse(is.na(match.idx), 
                            originalDF[,var], names(varLookup)[match.idx])
        originalDF
    }                            
    
    ADDLookup(df,"profession",profession.lookuptable)
      id         profession
    1  1       Optometrists
    2  2             Nurses
    3  3 Financial analysts
    4  4               <NA>
    5  5                  0
    6  6             Nurses
    

    请注意,现在我将数据框 df、相关变量的名称 var 作为文字字符传递,并将查找表本身作为参数传递。

    此外,您现在已经了解了为什么 $ 更多地用于交互使用而不是编程!因为它与传递给函数的参数不能很好地结合。对于这种类型的任务,您需要 [ 语法。

    【讨论】:

    • 感谢您花时间解决我的烂摊子。我不确定我是否完全理解这一切,但它完成了工作。谢谢!
    • 函数内的df不应该全部替换为originalDF吗?
    【解决方案3】:

    我会将查找表定义为因子。

    df[,"profession"] <- profession.lookuptable[df[,"profession"]]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-21
      • 1970-01-01
      相关资源
      最近更新 更多