Как преобразовать несколько категориальных переменных в фиктивные переменные в R? [Дубликат]

Альтернатива: полагайтесь на каскад вместо специфичности

. Ряд решений здесь рекомендуют использовать @import для включения вашего файла css4.css, а затем модифицировать селектора в нем, чтобы иметь большую специфичность или для использования объявления !important, но есть еще один способ.

Вставить все содержимое css4.css в конце css3.css. Таким образом, вам не нужно полагаться на !important или специфичность, потому что каскадное наследование примет ваши правила в конце файла, если они имеют одинаковую специфичность.

С помощью этого метода вы жертвуете

<div class="mycooldiv">Hello World</div>

Однако, это было бы достаточно легко создать большую специфичность, просто добавив html к началу каждого правила в css4.css, если вы не хотите вставлять его в конце css3.css. Это предпочтительнее добавления !important, где он работает.

Пример импорта, основанный на большей специфичности:

/* @import of css4.css with greater specificity */
html .mycooldiv {
    color: lime;
}

/* Contents of css3.css */
.mycooldiv {
    font: bold 1.2em sans-serif;
    color: tomato;
}
<div class="mycooldiv">Hello World</div>

16
задан Keith Hughitt 25 April 2013 в 15:14
поделиться

6 ответов

Еще лучше с помощью возможностей поиска @ AnandaMahto,

model.matrix(~ . + 0, data=df, contrasts.arg = lapply(df, contrasts, contrasts=FALSE))
#    v1a v1b v1c v2a v2b v2c
# 1    0   1   0   0   0   1
# 2    1   0   0   1   0   0
# 3    0   0   1   0   0   1
# 4    0   1   0   1   0   0
# 5    0   0   1   0   0   1
# 6    0   0   1   0   1   0
# 7    1   0   0   1   0   0
# 8    1   0   0   0   1   0
# 9    1   0   0   0   0   1
# 10   1   0   0   0   1   0

Я думаю, что это то, что вы ищете. Я был бы рад удалить, если это не так. Благодаря @ G.Grothendieck (еще раз) для превосходного использования из model.matrix!

cbind(with(df, model.matrix(~ v1 + 0)), with(df, model.matrix(~ v2 + 0)))
#    v1a v1b v1c v2a v2b v2c
# 1    0   1   0   0   0   1
# 2    1   0   0   1   0   0
# 3    0   0   1   0   0   1
# 4    0   1   0   1   0   0
# 5    0   0   1   0   0   1
# 6    0   0   1   0   1   0
# 7    1   0   0   1   0   0
# 8    1   0   0   0   1   0
# 9    1   0   0   0   0   1
# 10   1   0   0   0   1   0

Примечание: ваш результат просто:

with(df, model.matrix(~ v2 + 0))

Примечание 2: Это дает matrix. Довольно очевидно, но все же, оберните его as.data.frame(.), если вы хотите data.frame.

24
ответ дан Community 25 August 2018 в 00:55
поделиться

Достаточно прямой подход состоит в том, чтобы просто использовать table для каждого столбца, табулируя значения в столбце числом строк в data.frame:

allLevels <- levels(factor(unlist(df)))
do.call(cbind, 
        lapply(df, function(x) table(sequence(nrow(df)), 
                                     factor(x, levels = allLevels))))
#    a b c a b c
# 1  0 1 0 0 0 1
# 2  1 0 0 1 0 0
# 3  0 0 1 0 0 1
# 4  0 1 0 1 0 0
# 5  0 0 1 0 0 1
# 6  0 0 1 0 1 0
# 7  1 0 0 1 0 0
# 8  1 0 0 0 1 0
# 9  1 0 0 0 0 1
# 10 1 0 0 0 1 0

Я использовал factor на «x», чтобы убедиться, что даже в тех случаях, когда в столбце нет значений «c», на выходе все равно будет столбец «c», заполненный нулями.

3
ответ дан A5C1D2H2I1M1N2O1R2T1 25 August 2018 в 00:55
поделиться

Недавно я столкнулся с другим путем. Я заметил, что когда вы запускаете любую из функций контраста с contrasts, установленной в FALSE, она дает вам одну горячую кодировку. Например, contr.sum(5, contrasts = FALSE) дает

  1 2 3 4 5
1 1 0 0 0 0
2 0 1 0 0 0
3 0 0 1 0 0
4 0 0 0 1 0
5 0 0 0 0 1

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

contr.onehot = function (n, contrasts, sparse = FALSE) {
  contr.sum(n = n, contrasts = FALSE, sparse = sparse)
}

options(contrasts = c("contr.onehot", "contr.onehot"))
model.matrix(~ . - 1, data = df)

Это приводит к

   v1a v1b v1c v2a v2b v2c
1    0   0   1   0   0   1
2    0   1   0   1   0   0
3    0   0   1   0   1   0
4    1   0   0   0   1   0
5    0   1   0   0   1   0
6    0   1   0   0   0   1
7    1   0   0   0   1   0
8    0   1   0   0   1   0
9    0   1   0   1   0   0
10   0   0   1   0   0   1
3
ответ дан Andrew 25 August 2018 в 00:55
поделиться

Только что увиденный закрытый вопрос, который был здесь задан, и никто еще не упомянул об использовании пакета dummies:

Вы можете перекодировать свои переменные с помощью функции dummy.data.frame(), которая построена поверх model.matrix(), но имеет более простой синтаксис, некоторые хорошие параметры и вернет dataframe:

> dummy.data.frame(df, sep="_")
   v1_a v1_b v1_c v2_a v2_b v2_c
1     0    1    0    0    0    1
2     1    0    0    1    0    0
3     0    0    1    0    0    1
4     0    1    0    1    0    0
5     0    0    1    0    0    1
6     0    0    1    0    1    0
7     1    0    0    1    0    0
8     1    0    0    0    1    0
9     1    0    0    0    0    1
10    1    0    0    0    1    0

Некоторые приятные аспекты этой функции - вы можете легко определить разделитель для новых имен (sep=), (all=F) и имеет свой собственный вариант dummy.classes, который позволяет указать, какие классы столбца должны быть закодированы.

Вы также можете просто использовать функцию dummy(), чтобы применить это к всего один столбец.

3
ответ дан Andrew Haynes 25 August 2018 в 00:55
поделиться

В пакете Вайта есть функция, которая делает то, что вам нужно, dummyVars. Вот пример его использования, взятый из документации авторов: http://topepo.github.io/caret/preprocess.html

library(earth)
data(etitanic)

dummies <- caret::dummyVars(survived ~ ., data = etitanic)
head(predict(dummies, newdata = etitanic))

  pclass.1st pclass.2nd pclass.3rd sex.female sex.male     age sibsp parch
1          1          0          0          1        0 29.0000     0     0
2          1          0          0          0        1  0.9167     1     2
3          1          0          0          1        0  2.0000     1     2
4          1          0          0          0        1 30.0000     1     2
5          1          0          0          1        0 25.0000     1     2
6          1          0          0          0        1 48.0000     0     0

Параметры model.matrix может быть полезно, если у вас были разреженные данные и вы хотели использовать Matrix::sparse.model.matrix

8
ответ дан marbel 25 August 2018 в 00:55
поделиться

Вот решение для более общего случая, когда количество букв не указано apriori:

convertABC <- function(x) {

    hold <- rep(0,max(match(as.matrix(df),letters))) # pre-format output

    codify <- function(x) {                          # define function for single char

        output <- hold                               # take empty vector
        output[match(x,letters)] <- 1                # place 1 according to letter pos
        return(output)
    }

    to.return <- t(sapply(as.character(x),codify))   # apply it to whole vector
    rownames(to.return) <- 1:nrow(to.return)         # nice rownames
    colnames(to.return) <- do.call(c,list(letters[1:max(match(as.matrix(df),letters))])) # nice columnnames
    return(to.return)
}

Эта функция принимает вектор символов и перекодирует его в двоичные значения. Для обработки всех переменных в df:

do.call(cbind,lapply(df,convertABC))
0
ответ дан Maxim.K 25 August 2018 в 00:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: