Мне приходится создавать фиктивные переменные таким специфическим способом. Может кто-нибудь помочь мне упаковать этот код в функцию?
respect$BB6_cat5_0 <- ifelse(respect$BB6_cat5 == 1, 1, 0)
respect$BB6_cat5_1 <- ifelse(respect$BB6_cat5 == 2, 1, 0)
respect$BB6_cat5_2 <- ifelse(respect$BB6_cat5 == 3, 1, 0)
respect$BB6_cat5_3 <- ifelse(respect$BB6_cat5 == 4, 1, 0)
respect$BB6_cat5_4 <- ifelse(respect$BB6_cat5 == 5, 1, 0)
respect$J1A_cat2_0 <- ifelse(respect$J1A_cat2 == 1, 1, 0)
respect$J1A_cat2_1 <- ifelse(respect$J1A_cat2 == 2, 1, 0)
Длины категорий варьируются для переменных, и наименование фиктивных переменных очень важно для моего проекта.
Я пробовал следующее, но это не учитывает референтную переменную из-за того, как работает model.matrix.
dummy.fun<-function(data) {
data_factor<-data.frame(lapply(data,as.factor))
names(data_factor)<-paste0(names(data_factor),'_')
data_all<-data.frame(model.matrix(~.+0,data=data_factor))
}
dummy.fun(respect)
Однако это не дает мне BB6_cat5_0, если это не первая переменная в наборе данных. Любые идеи, как сверху, как я могу получить эту функцию для вывода всех фиктивных переменных, даже ссылки?
3 ответа
Попробуйте с помощью этой функции:
# Sample data:
set.seed(123)
df <- data.frame(a = sample(letters[1:3], 10, replace = T),
b = sample(1:2, 10, replace = T))
# Function:
vars_to_dummy <- function(df, vars) {
stopifnot(all(vars %in% names(df)))
for (i in vars) {
dummy_names <- sort(unique(df[[i]]))
dummy_i <- as.data.frame(
sapply(dummy_names, function(x) {
(df[[i]] == x)*1
}, USE.NAMES = TRUE)
)
names(dummy_i) <- paste(names(df[i]), dummy_names, sep = "_")
df <- cbind(df, dummy_i)
}
return(df)
}
# Try that:
vars_to_dummy(df, vars = c("a", "b"))
> vars_to_dummy(df, vars = c("a", "b"))
a b a_a a_b a_c b_1 b_2
1 a 2 1 0 0 0 1
2 c 1 0 0 1 1 0
3 b 2 0 1 0 0 1
4 c 2 0 0 1 0 1
5 c 1 0 0 1 1 0
6 a 2 1 0 0 0 1
7 b 1 0 1 0 1 0
8 c 1 0 0 1 1 0
9 b 1 0 1 0 1 0
10 b 2 0 1 0 0 1
Редактировать:
df
это ваш фрейм данных, vars
символьный вектор, обозначающий имена столбцов, для которых вы хотите макеты.
Я уверен, что есть более хороший способ сделать это (двойной цикл for не очень приятное зрелище), но следующее должно делать то, что вы хотите:
respect <- list(BB6_cat5 = 1,BB6_cat0 = 2, BB6_cat1 = 3)
respect_names <- names(respect)
for(pos in 1:length(respect_names)){
for(i in 0:4) respect[[paste0(respect_names[pos],"_",i)]] = ifelse(respect[[(respect_names[pos])]] == (i+1),1,0)
}
respect
Первый уровень проходит по оригинальным именованным элементам в отношении. Второй уровень перебирает значения, которые вы хотите проверить. Он использует синтаксис [[]] для добавления значений в список и поддержания согласованности теста.
dummy.fun<-function(data) {
data_factor<-data.frame(lapply(data,as.factor))
names(data_factor)<-paste0(names(data_factor),'_')
data_all<-data.frame(model.matrix(~.+0,data=data_factor,
contrasts.arg=lapply(data_factor[sapply,as.factor],contrasts,contrasts=FALSE)))
}