r语言 - 在 data.frame 中按名称访问列:如果列不存在,则返回 NA



是否有更有效的方法通过列的名称检查列的存在,如果存在则返回column,如果不存在则返回na?

现在我使用以下功能:

TryGetColumn <- function(x, column.name, column.names, value.if.not.exists) {
    if (column.name %in% column.names) {
        x[, column.name]
    } else {
        value.if.not.exists
    }
}
df <- data.frame(a = 1:5, b = 6:10)
col.names <- colnames(df)
ab <- TryGetColumn(df, "a", col.names, NA) + TryGetColumn(df, "b", col.names, NA)
ac <- TryGetColumn(df, "a", col.names, NA) + TryGetColumn(df, "c", col.names, NA)
ab
#[1]  7  9 11 13 15
ac
#[1] NA NA NA NA NA

编辑:根据Gregor的回答,我重写了以下代码:

col.names <- c("a", "b", "c")
col.matches <- as.list(col.names %in% colnames(df))
names(col.matches) <- col.names
TryGetColumn <- function(col.name) if (col.matches[[col.name]]) df[, col.name] else NA
ab <- TryGetColumn("a") + TryGetColumn("b")
ac <- TryGetColumn("a") + TryGetColumn("c")

现在它基于关联数组(list),并且应该比每次TryGetColumn调用的线性查找更快。

我会使用match

match(x = c("mpg", "disp", "blarg"), table = names(mtcars), nomatch = NA)
# [1]  1  3 NA

如果您编写包装器,则不需要分别传递数据帧及其列:

column_index <- function(data, column.names, value.if.not.exists = NA) {
    match(x = column.names, table = names(data), nomatch = value.if.not.exists)
}

编辑

哦,我以为你想要列索引。您希望返回一整列。为此,你的功能看起来不错,我只想稍微简化一下:

TryGetColumn <- function(x, column.name, value.if.not.exists = NA) {
    if (column.name %in% names(x)) {
        return(x[, column.name])
    } 
    return(value.if.not.exists)
}

如果你经常使用它,并且真的很担心计算时间,那么一次检查一堆列名会更快(如我答案的顶部所示),然后只从数据帧中提取现有列,并根据需要生成尽可能多的NA列。但是,如果你关心计算时间,我敢打赌,无论你在做什么,这一特定步骤都不会减慢你的速度。

最新更新