Проверка, имеют ли элементы в векторе, соответствующие именам переменных, символьный класс в фрейме данных - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь создать предохранитель для своей функции. Я хотел бы, чтобы он взял ввод фрейма данных и вектор имен переменных для проверки класса. Я бы хотел, чтобы он попытался принудительно вызвать любую переменную, которая не соответствует символу, отправить предупреждение или, если принудительное завершение не удалось, остановите процесс.

Это то, что я получил до сих пор:

#Inputs
varlist <- c("varA","varB","varC")
df <- data.frame(matrix(ncol=4,nrow=0, dimnames=list(NULL, c("varA", "varB", "varC","varD"))))
df$varA <- as.character(df$varA)
df$varB <- as.character(df$varB)
df$varC <- as.factor(df$varC)
df$varD <- as.numeric(df$varD)

for(i in 1:length(varlist)){
   if(!(purrr::pmap(select(df, varlist[i]), ~is.character)==TRUE)){
        df$varlist[i] <- as.character(df$varlist[i])
        warning(paste0("Coercing variable", varlist[i], "to character"))
        stopifnot(is.character(df$varlist[i]))
 } 
}

Однако это не удается,

Error in if (!(purrr::pmap(select(df, varlist[i]), ~is.character) == TRUE)) { : 
  argument is of length zero

Есть ли простой способ сделать это?

Ожидаемый результат

#output console warning
Warning: Coercing variable varC to character

#Manual checks
is.character(df$varA) == TRUE #included in varlist
is.character(df$varB) == TRUE #included in varlist
is.character(df$varC) == TRUE #included in varlist, coerced from factor to character
is.character(df$varD) == FALSE #not included in varlist


1 Ответ

0 голосов
/ 12 марта 2020

У меня есть кое-что, что, я думаю, будет работать в течение oop. Если ваш фрейм данных довольно большой и содержит много столбцов, есть способ применить его, чтобы ускорить его, но это более точно соответствует тому, что вы изначально имели.

Создание данных

varlist <- c("varA","varB","varC")
df <- data.frame(varA = letters[1:4],
                 varB = letters[11:14],
                 varC = letters[21:24],
                 varD = 1:4)
df$varA <- as.character(df$varA)
df$varB <- as.character(df$varB)
df$varC <- as.factor(df$varC)
df$varD <- as.numeric(df$varD)

Я не добавил ручную ошибку, если as.character завершился неудачно, потому что эта функция сделает это самостоятельно.

    for(i in (1:ncol(df))[colnames(df) %in% varlist]){
    df[,i] <- as.character(df[,i])
  if(!(is.character(df[,i]))){
    warning(paste("Coercing variable", colnames(df)[i], "to character"))
  }
}

Использование Map

Обновите, чтобы сделать то же самое, используя Map, который является многовариантной версией apply:

char_function <- function(x, name){
  y <- as.character(x)
  if(!(is.character(x))){
    warning((paste("Coercing variable", name, "to character")))
  } 
  return(y)
}

df.char <- data.frame(Map(char_function, df[varlist], names(df[varlist])), stringsAsFactors = F)

Для кадра данных с 4 столбцами и 2600 строками для l oop потребовалось 0,015 se c и Map заняли 0,012 сек c. В зависимости от размера вашего фрейма данных, возможно, стоит использовать Map

...