2

在flodel的帮助下,我找到了一种用查找表中的值标签替换数字代码的方法

像我一样雄心勃勃,我现在想把它变成一个函数。此外,我有很多查找表需要快速查找我的数据,这样一个函数就会很方便。

但首先是一些样本数据,从数据框开始,

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向我展示了如何用查找表中的值标签替换数字代码。像这样,

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

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

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

感谢您的阅读。

4

3 回答 3

4

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

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

例如,您的前几行paste(originalDF,'$',originalVAR,sep='')等似乎期望originalDF并且originalVARstrings,而您将DF.VAR成为string 'df$profession'。但是,当您这样做时,您match似乎想DF.VAR成为变量 df$profession

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

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

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

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

为此,您可以使用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])

请注意,我们实际上并没有修改df您作为参数传入的数据框ADDlookup;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 函数不会修改传递给它们的参数。


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

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

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

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

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

ADDlookup( df, 'profession', profession.lookup )
于 2012-04-04T04:45:26.050 回答
3

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

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作为文字字符传递,并将查找表本身作为参数传递。

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

于 2012-04-04T04:45:13.973 回答
0

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

df[,"profession"] <- profession.lookuptable[df[,"profession"]]
于 2012-04-04T10:42:43.657 回答