我有一个名为granular的数据框架,在相关部分中包含:
GranularClass,其值之一为"Constitutional Law I Spring 2016",以及Knowledge。数值列包含NAs。我试图编写一个函数来计算给定列的非NA值,条件是给定的因子值。但是,我试图计算值的行为是不同的,这取决于我是把它写成函数还是只在控制台中使用它。
更具体地说,以下代码失败:
# take subset of the dataframe containing only the factor values I want to look at:
isolate <- function(class) {
return(granular[granular$GranularClass == class, ])
}
# count non-NA values:
cr <- function(df, column){
return(sum(!is.na(df$column)))
}
# this fails
cr(isolate("Constitutional Law I Spring 2016"), Knowledge)最后一次调用提供了不正确的输出(只返回0),并引发警告:
Warning message:
In is.na(df$column) :
is.na() applied to non-(list or vector) of type 'NULL'然而,这是成功的:
sum(!is.na(isolate("Constitutional Law I Spring 2016")$Knowledge))
# gives correct output: [1] 62然后,所以..。哈?我认为,最后一个块中的工作代码在语义上与第一个爆炸块中的函数调用相同。但很明显这不对。
我是否以某种方式将列名传递到函数中?(我应该把它当作字符串传递吗?但是this prior SO建议您不能将字符串传递到$运算符。
发布于 2016-08-24 19:06:44
现在我已经写了两段作为评论,我将给出一个答案:
$不计算/解析后面的列名。如果要使用变量列名,最简单的方法是使用带有[或[[的字符串列名,而不是$。例如,试试x = 'mpg',mtcars$mpg;mtcars$x;mtcars[, mpg];mtcars[, 'mpg'];mtcars[, x]。特别要注意的是,mtcars$x不返回列,尽管x被定义为'mpg',并且有一个名为'mpg'的列。这是问题的根源,也是您链接到的问题的要点,Select a data frame column using $ and the name of the column as a string in a variable。在函数中使用$并不重要。
另见fortunes::fortune(312)和fortunes::fortune(343)。
但是mtcars$x不会抛出错误-它返回NULL,因为没有名为'x'的列。因此,您所观察到的行为上的差异是因为您对结果做了不同的事情,而抛出错误的是下游调用。is.na(NULL)给出了一个警告和一个0长度的结果--这是可加到0的.但这里没有错误。
您的isolate函数很奇怪,因为它依赖于在全局环境中有一个名为granular的数据框架和一个名为GranularClass的列。更好的做法是传递数据框架,但无论如何。这并不重要,除非此函数在提交给CRAN的包中。
当您执行df$column时,即使column是cr函数的一个参数,因为它在这里被用作$的参数,而$是特殊的,但是column不会被计算。
要使您的函数正常工作,您应该重写它
cr = function(df, column) sum(!is.na(df[, column]))把它叫做
cr(isolate("Constitutional Law I Spring 2016"), "Knowledge")使用字符串作为列名是传递列名作为参数的唯一简单方法。
如果确实希望传递未引用的列名,请使用lazyeval包。它的韵律很好。但是它将像上面那样编写标准评估版本,并围绕它编写一个非标准的评估包装器。一般情况下都不值得这么麻烦。
https://stackoverflow.com/questions/39130840
复制相似问题