我想验证data.frame
是否包含具有特定名称的列。理想情况下,这将是一个实用函数,我可以只传递data.frame
和期望的列名,如果data.frame
不包含期望的列,则该函数将引发错误。我在下面编写了自己的函数,但是,这似乎已经存在于R生态系统中。
我的问题是:
我为此编写的函数示例:
validate_df_columns <- function(df, columns) {
chr_df <- deparse(substitute(df))
chr_columns <- paste(columns, collapse = ", ")
if (!('data.frame' %in% class(df))) {
stop(paste("Argument", df, "must be a data.frame."))
}
if (sum(colnames(df) %in% columns) != length(columns)) {
stop(paste(chr_df, "must contain the columns", chr_columns))
}
}
validate_df_columns(data.frame(a=1:3, b=4:6), c("a", "b", "c'"))
## Error in validate_df_columns(data.frame(a = 1:3, b = 4:6), c("a", "b", :
## data.frame(a = 1:3, b = 4:6) must contain the columns a, b, c'
答案 0 :(得分:3)
tibble
中的软件包rlang
和tidyverse
具有检查此功能的功能:
library(tibble) # or library(rlang) or library(tidyverse)
has_name(iris, c("Species","potatoe"))
# [1] TRUE FALSE
从技术上讲,它位于rlang
中,其代码仅为:
function (x, name)
{
name %in% names2(x)
}
其中rlang::names2
是base::names
的增强版本,当对象没有名称时,它返回空字符串向量,而不是NULL
。
这是一种重写函数的方法:
validate_df_columns <- function(df, columns){
if (!is.data.frame(df)) {
stop(paste("Argument", deparse(substitute(df)), "must be a data.frame."))
}
if(!all(i <- rlang::has_name(df,columns)))
stop(sprintf(
"%s doesn't contain: %s",
deparse(substitute(df)),
paste(columns[!i], collapse=", ")))
}
validate_df_columns(iris, c("Species","potatoe","banana"))
# Error in validate_df_columns(iris, c("Species", "potatoe", "banana")) :
# iris doesn't contain: potatoe, banana
在这里使用deparse(substitute(...))
对我来说意义不大,因为它不是交互式使用的,所以我认为只说"df"
就更清楚了。
答案 1 :(得分:0)
%in%
运算符可以处理成对的向量,因此我们已经可以使用单线了。考虑:
df <- data.frame(a=c(1:3), b=c(4:6), c=c(7:9))
names <- c("a", "c", "blah", "doh")
names[names %in% names(df)]
[1] "a" "c"
如果要断言数据框包含所有输入名称,则只需使用:
length(names %in% names(df)) == length(names) # to check all inputs are present
length(names %in% names(df)) == length(names(df)) # to check that input matches df