R-在对不同数据帧的列进行类型检查时出现意外行为



我正在处理一些有数百个协变量的数据,所以我决定编写一些函数,使预处理更快、更干净(比如缩放某些数值变量(。所有这些函数的一个重要部分是在对列应用特定函数之前对列进行类型检查。

这是我缩放连续列的函数:

# rm (vector): names of columns not to be scaled
scale.continuous <- function(df, rm=NULL) {
cols <- setdiff(colnames(df), rm)
for(col in cols) {
if(is.numeric(df[,col])){
df[,col] <- as.numeric(scale(df[,col]))
}
}
df
}

如果我使用read.csv()加载数据帧,这可以很好地工作,但我拥有的数据很大,因此从readr/tidyverse使用read_csv()的速度提升非常显著。不幸的是,如果我使用read_csv()加载数据,我的所有函数都会中断。

我将问题缩小到了类型检查,特别是当通过列名为的字符串对我正在访问的列进行类型检查时。这里有一些代码来演示我的意思:

# When using read.csv()
> is.numeric(df$col)
[1] TRUE
> is.numeric(df[,"col"])
[1] TRUE
# When using read_csv()
> is.numeric(df$col)
[1] TRUE
> is.numeric(df[,"col"])
[1] FALSE

我意识到这里的问题是,按照上面的方法用字符串对数据帧进行索引会返回tibble,而不是像其他索引方法那样返回常规列表。我不明白的是,为什么存在这种行为,为什么as.numeric()(或任何类型检查(不能与tibble一起工作,以及通常为什么默认数据帧和tidyverse数据帧的构建方式存在这种差异。此外,如果知道read_csv()中是否有我可以更改的参数,将使这种类型的索引的行为与默认数据帧相同,那就太好了。


我应该提到,我意识到可能有更好的方法来编写这段代码(例如,只使用df$"col"来索引修复问题(,但我仍然不明白第一种方法的问题根源是什么。我现在正在处理更大的数据集,这些数据集需要比我过去习惯的更多的预处理,所以我想尽可能完整地了解我正在使用的数据结构。

Tibbles在使用[提取函数时,与常规数据帧相比,其默认行为略有不同,这可能有点棘手。具体来说,tibble上的df[,"col"]将返回一列tibble,而在常规数据帧上,它将返回一个向量。所以你需要使用:

df[["col"]]

或者明确声明您希望强制到最低维度并执行:

df[, "col", drop = TRUE]

来自文件:

df[,j]返回一个tibble;它不会自动提取列在…内df[,j,drop=FALSE]是默认值。

最新更新