Как построить функцию для создания фиктивных переменных? - PullRequest
1 голос
/ 02 августа 2020

У меня есть фрейм данных, который дает следующий вывод для создания фиктивных переменных.

library(dummies)
df1 <- data.frame(id = 1:4, year = 1991:1994)
df1 <- cbind(df1, dummy(df1$year, sep = "_"))
df1
#    id year df1_1991 df1_1992 df1_1993 df1_1994
#1  1 1991        1        0        0        0
#2  2 1992        0        1        0        0
#3  3 1993        0        0        1        0
#4  4 1994        0        0        0        1

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

dummy_df <- function(dframe, x){
    dframe <- cbind(dframe, dummy(dframe$x, sep = "_"))
    return(dframe)
}

Однако когда я запускаю вывод, я получаю следующую ошибку.

dummy_df(df1, year)
#Error in `[[.default`(x, 1) : subscript out of bounds

Как исправить эту ошибку и создать автоматическую c функцию для создания фиктивных переменных? Кроме того, было бы лучше, если бы функция предоставляла возможность сохранять или отбрасывать исходный столбец, который разделяется для создания фиктивных переменных. Например, в случае вышеуказанного фрейма данных опция «сохранить» или «отменить» должна быть применена к столбцу year.

Этот вопрос был опубликован после рассмотрения аналогичного вопроса здесь. Передать в функцию имя столбца data.frame

1 Ответ

1 голос
/ 02 августа 2020

Проблема в том, что когда year передается без кавычек, это символ, представляющий переменную, а не строку или имя переменной. Стандартный прием для получения символьной строки - использование deparse(substitute(.)). Затем работает экстрактор [[.

dummy_df <- function(dframe, x){
    x <- deparse(substitute(x))
    dframe <- cbind(dframe, dummy(dframe[[x]], sep = "_"))
    return(dframe)
}

dummy_df(df1, year)
#  id year df1_1991 df1_1992 df1_1993 df1_1994
#1  1 1991        1        0        0        0
#2  2 1992        0        1        0        0
#3  3 1993        0        0        1        0
#4  4 1994        0        0        0        1
#Warning message:
#In model.matrix.default(~x - 1, model.frame(~x - 1), contrasts = FALSE) :
#  non-list contrasts argument ignored

Если столбец x можно передать в кавычки, измените функцию выше на as.character(substitute(.)). Функция принимает как заключенные в кавычки, так и не заключенные в кавычки x.

dummy_df <- function(dframe, x){
    x <- as.character(substitute(x))
    dframe <- cbind(dframe, dummy(dframe[[x]], sep = "_"))
    return(dframe)
}

dummy_df(df1, year)
dummy_df(df1, "year")

Редактировать

После комментария OP сохранить или удалить столбец x можно решается с помощью дополнительного аргумента функции, keep, по умолчанию TRUE.

dummy_df <- function(dframe, x, keep = TRUE){
    x <- as.character(substitute(x))
    if(keep){
        dftmp <- dframe
    } else {
        i <- grep(x, names(dframe))
        if(length(i) == 0) stop(paste(sQuote(x), "is not a valid column"))
        dftmp <- dframe[-i]
    }
    dframe <- cbind(dftmp, dummy(dframe[[x]], sep = "_"))
    return(dframe)
}

dummy_df(df1, year)
dummy_df(df1, "year")

dummy_df(df1, year, keep = FALSE)
dummy_df(df1, month, keep = FALSE)
...