Функция в R для проверки существования определенных столбцов на data.frame - PullRequest
0 голосов
/ 05 ноября 2018

Я хотел бы проверить, что data.frame содержит столбцы с конкретными именами. В идеале это была бы служебная функция, в которую я мог бы просто передать data.frame и ожидаемые имена столбцов, и функция выдаст ошибку, если data.frame не содержит ожидаемые столбцы. Я написал свою собственную функцию ниже, однако, похоже, что она уже существует в экосистеме R.

Мои вопросы:

  1. Такая функция (или однострочная) уже существует либо в базе R, либо в общем пакете?
  2. Если нет, какие-либо предложения для моей функции (ниже)?

Пример функции, которую я написал для этого:

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'

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Пакеты 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".

0 голосов
/ 05 ноября 2018

Оператор %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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...