按名称访问 data.frame 中的列:return 如果列不存在则不适用
Accessing column by name in data.frame: return NA if column doesn't exists
是否有更有效的方法来通过名称检查列是否存在,returning column if exists or return na if it doesn't exists?
现在我正在使用以下功能:
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's 答案,我重写了以下代码:
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")
现在它基于关联数组(列表)并且在每次 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)
}
编辑
糟糕,我以为您需要列索引。您想要 return 一个完整的专栏。为此,您的函数看起来不错,我只是稍微简化一下:
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
列。但是,如果您担心计算时间,我敢打赌,无论您在做什么,这个特定步骤都不会拖慢您的速度。
是否有更有效的方法来通过名称检查列是否存在,returning column if exists or return na if it doesn't exists?
现在我正在使用以下功能:
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's 答案,我重写了以下代码:
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")
现在它基于关联数组(列表)并且在每次 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)
}
编辑
糟糕,我以为您需要列索引。您想要 return 一个完整的专栏。为此,您的函数看起来不错,我只是稍微简化一下:
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
列。但是,如果您担心计算时间,我敢打赌,无论您在做什么,这个特定步骤都不会拖慢您的速度。