. Ряд решений здесь рекомендуют использовать @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>
Еще лучше с помощью возможностей поиска @ 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
.
Достаточно прямой подход состоит в том, чтобы просто использовать 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», заполненный нулями.
Недавно я столкнулся с другим путем. Я заметил, что когда вы запускаете любую из функций контраста с 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
Только что увиденный закрытый вопрос, который был здесь задан, и никто еще не упомянул об использовании пакета 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()
, чтобы применить это к всего один столбец.
В пакете Вайта есть функция, которая делает то, что вам нужно, 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
Вот решение для более общего случая, когда количество букв не указано 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))