Tengo problemas para generar las siguientes variables ficticias en R:
Estoy analizando datos de series de tiempo anuales (período de tiempo 1948-2009). Tengo dos preguntas:
¿Cómo puedo generar una variable ficticia para la observación n. ° 10, es decir, para el año 1957 (valor = 1 en 1957 y cero en caso contrario)?
¿Cómo genero una variable ficticia que es cero antes de 1957 y toma el valor 1 desde 1957 en adelante hasta 2009?
+ 0
o- 1
. Pormodel.matrix(~ year.f + 0)
lo tanto , dará variables ficticias sin un nivel de referencia.La forma más sencilla de producir estas variables ficticias es algo como lo siguiente:
> print(year) [1] 1956 1957 1957 1958 1958 1959 > dummy <- as.numeric(year == 1957) > print(dummy) [1] 0 1 1 0 0 0 > dummy2 <- as.numeric(year >= 1957) > print(dummy2) [1] 0 1 1 1 1 1
De manera más general, puede utilizar
ifelse
para elegir entre dos valores según una condición. Entonces, si en lugar de una variable ficticia 0-1, por alguna razón quisiera usar, digamos, 4 y 7, podría usarifelse(year == 1957, 4, 7)
.fuente
Usando dummies :: dummy () :
library(dummies) # example data 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
fuente
El paquete
mlr
incluyecreateDummyFeatures
para este propósito:library(mlr) df <- data.frame(var = sample(c("A", "B", "C"), 10, replace = TRUE)) df # var # 1 B # 2 A # 3 C # 4 B # 5 C # 6 A # 7 C # 8 A # 9 B # 10 C createDummyFeatures(df, cols = "var") # var.A var.B var.C # 1 0 1 0 # 2 1 0 0 # 3 0 0 1 # 4 0 1 0 # 5 0 0 1 # 6 1 0 0 # 7 0 0 1 # 8 1 0 0 # 9 0 1 0 # 10 0 0 1
createDummyFeatures
elimina la variable original.https://www.rdocumentation.org/packages/mlr/versions/2.9/topics/createDummyFeatures
.....
fuente
Las otras respuestas aquí ofrecen rutas directas para realizar esta tarea, una que muchos modelos (por ejemplo
lm
) harán por usted internamente de todos modos. No obstante, aquí hay formas de crear variables ficticias con los paquetescaret
y populares de Max Kuhnrecipes
. Aunque son algo más detallados, ambos escalan fácilmente a situaciones más complicadas y encajan perfectamente en sus respectivos marcos.caret::dummyVars
Con
caret
, la función relevante esdummyVars
, que tiene unpredict
método para aplicarla en un marco de datos:df <- data.frame(letter = rep(c('a', 'b', 'c'), each = 2), y = 1:6) library(caret) dummy <- dummyVars(~ ., data = df, fullRank = TRUE) dummy #> Dummy Variable Object #> #> Formula: ~. #> 2 variables, 1 factors #> Variables and levels will be separated by '.' #> A full rank encoding is used predict(dummy, df) #> letter.b letter.c y #> 1 0 0 1 #> 2 0 0 2 #> 3 1 0 3 #> 4 1 0 4 #> 5 0 1 5 #> 6 0 1 6
recipes::step_dummy
Con
recipes
, la función relevante esstep_dummy
:library(recipes) dummy_recipe <- recipe(y ~ letter, df) %>% step_dummy(letter) dummy_recipe #> Data Recipe #> #> Inputs: #> #> role #variables #> outcome 1 #> predictor 1 #> #> Steps: #> #> Dummy variables from letter
Según el contexto, extraiga los datos con
prep
y conbake
ojuice
:# Prep and bake on new data... dummy_recipe %>% prep() %>% bake(df) #> # A tibble: 6 x 3 #> y letter_b letter_c #> <int> <dbl> <dbl> #> 1 1 0 0 #> 2 2 0 0 #> 3 3 1 0 #> 4 4 1 0 #> 5 5 0 1 #> 6 6 0 1 # ...or use `retain = TRUE` and `juice` to extract training data dummy_recipe %>% prep(retain = TRUE) %>% juice() #> # A tibble: 6 x 3 #> y letter_b letter_c #> <int> <dbl> <dbl> #> 1 1 0 0 #> 2 2 0 0 #> 3 3 1 0 #> 4 4 1 0 #> 5 5 0 1 #> 6 6 0 1
fuente
Para el caso de uso como se presenta en la pregunta, también puede simplemente multiplicar la condición lógica con
1
(o tal vez incluso mejor, con1L
):# example data df1 <- data.frame(yr = 1951:1960) # create the dummies df1$is.1957 <- 1L * (df1$yr == 1957) df1$after.1957 <- 1L * (df1$yr >= 1957)
lo que da:
Para los casos de uso que se presentan, por ejemplo, en las respuestas de @ zx8754 y @Sotos, todavía hay algunas otras opciones que aún no se han cubierto en mi opinión.
1) Crea tu propia
make_dummies
función# example data df2 <- data.frame(id = 1:5, year = c(1991:1994,1992)) # create a function make_dummies <- function(v, prefix = '') { s <- sort(unique(v)) d <- outer(v, s, function(v, s) 1L * (v == s)) colnames(d) <- paste0(prefix, s) d } # bind the dummies to the original dataframe cbind(df2, make_dummies(df2$year, prefix = 'y'))
lo que da:
2) utilice la función
dcast
-detabla de datos o reshape2lo que da:
Sin embargo, esto no funcionará cuando haya valores duplicados en la columna para los que se deben crear las variables ficticias. En el caso de que se necesite una función de agregación específica
dcast
y el resultado de ladcast
necesidad de fusionarse con el original:# example data df3 <- data.frame(var = c("B", "C", "A", "B", "C")) # aggregation function to get dummy values f <- function(x) as.integer(length(x) > 0) # reshape to wide with the cumstom aggregation function and merge back to the original merge(df3, dcast(df3, var ~ var, fun.aggregate = f), by = 'var', all.x = TRUE)
que da (tenga en cuenta que el resultado está ordenado de acuerdo con la
by
columna):3) usa el
spread
-detidyr(conmutate
dedplyr)library(dplyr) library(tidyr) df2 %>% mutate(v = 1, yr = year) %>% spread(yr, v, fill = 0)
lo que da:
fuente
Lo que normalmente hago para trabajar con este tipo de variables ficticias es:
(1) ¿cómo genero una variable ficticia para la observación n. ° 10, es decir, para el año 1957 (valor = 1 en 1957 y cero en caso contrario)
data$factor_year_1 <- factor ( with ( data, ifelse ( ( year == 1957 ), 1 , 0 ) ) )
(2) ¿cómo genero una variable ficticia que es cero antes de 1957 y toma el valor 1 desde 1957 en adelante hasta 2009?
data$factor_year_2 <- factor ( with ( data, ifelse ( ( year < 1957 ), 0 , 1 ) ) )
Entonces, puedo introducir este factor como una variable ficticia en mis modelos. Por ejemplo, para ver si existe una tendencia a largo plazo en una variable
y
:¡Espero que esto ayude!
fuente
Si desea obtener K variables ficticias, en lugar de K-1, intente:
dummies = table(1:length(year),as.factor(year))
Mejor,
fuente
as.data.frame.matrix(dummies)
para traducirlo en unoLeí esto en el foro de kaggle:
#Generate example dataframe with character column example <- as.data.frame(c("A", "A", "B", "F", "C", "G", "C", "D", "E", "F")) names(example) <- "strcol" #For every unique value in the string column, create a new 1/0 column #This is what Factors do "under-the-hood" automatically when passed to function requiring numeric data for(level in unique(example$strcol)){ example[paste("dummy", level, sep = "_")] <- ifelse(example$strcol == level, 1, 0) }
fuente
La
ifelse
función es mejor para una lógica simple como esta.> x <- seq(1950, 1960, 1) ifelse(x == 1957, 1, 0) ifelse(x <= 1957, 1, 0) > [1] 0 0 0 0 0 0 0 1 0 0 0 > [1] 1 1 1 1 1 1 1 1 0 0 0
Además, si desea que devuelva datos de caracteres, puede hacerlo.
> x <- seq(1950, 1960, 1) ifelse(x == 1957, "foo", "bar") ifelse(x <= 1957, "foo", "bar") > [1] "bar" "bar" "bar" "bar" "bar" "bar" "bar" "foo" "bar" "bar" "bar" > [1] "foo" "foo" "foo" "foo" "foo" "foo" "foo" "foo" "bar" "bar" "bar"
Variables categóricas con anidamiento ...
> x <- seq(1950, 1960, 1) ifelse(x == 1957, "foo", ifelse(x == 1958, "bar","baz")) > [1] "baz" "baz" "baz" "baz" "baz" "baz" "baz" "foo" "bar" "baz" "baz"
Ésta es la opción más sencilla.
fuente
Otra forma es usar
mtabulate
desde elqdapTools
paquete, es decirdf <- data.frame(var = sample(c("A", "B", "C"), 5, replace = TRUE)) var #1 C #2 A #3 C #4 B #5 B library(qdapTools) mtabulate(df$var)
lo que da,
fuente
Convierta sus datos en una tabla de datos y use el conjunto por referencia y filtrado de filas
library(data.table) dt <- as.data.table(your.dataframe.or.whatever) dt[, is.1957 := 0] dt[year == 1957, is.1957 := 1]
Ejemplo de juguete de prueba de concepto:
library(data.table) dt <- as.data.table(cbind(c(1, 1, 1), c(2, 2, 3))) dt[, is.3 := 0] dt[V2 == 3, is.3 := 1]
fuente
Este forro en la base R
model.matrix( ~ iris$Species - 1)
da
iris$Speciessetosa iris$Speciesversicolor iris$Speciesvirginica 1 1 0 0 2 1 0 0 3 1 0 0 4 1 0 0 5 1 0 0 6 1 0 0 7 1 0 0 8 1 0 0 9 1 0 0 10 1 0 0 11 1 0 0 12 1 0 0 13 1 0 0 14 1 0 0 15 1 0 0 16 1 0 0 17 1 0 0 18 1 0 0 19 1 0 0 20 1 0 0 21 1 0 0 22 1 0 0 23 1 0 0 24 1 0 0 25 1 0 0 26 1 0 0 27 1 0 0 28 1 0 0 29 1 0 0 30 1 0 0 31 1 0 0 32 1 0 0 33 1 0 0 34 1 0 0 35 1 0 0 36 1 0 0 37 1 0 0 38 1 0 0 39 1 0 0 40 1 0 0 41 1 0 0 42 1 0 0 43 1 0 0 44 1 0 0 45 1 0 0 46 1 0 0 47 1 0 0 48 1 0 0 49 1 0 0 50 1 0 0 51 0 1 0 52 0 1 0 53 0 1 0 54 0 1 0 55 0 1 0 56 0 1 0 57 0 1 0 58 0 1 0 59 0 1 0 60 0 1 0 61 0 1 0 62 0 1 0 63 0 1 0 64 0 1 0 65 0 1 0 66 0 1 0 67 0 1 0 68 0 1 0 69 0 1 0 70 0 1 0 71 0 1 0 72 0 1 0 73 0 1 0 74 0 1 0 75 0 1 0 76 0 1 0 77 0 1 0 78 0 1 0 79 0 1 0 80 0 1 0 81 0 1 0 82 0 1 0 83 0 1 0 84 0 1 0 85 0 1 0 86 0 1 0 87 0 1 0 88 0 1 0 89 0 1 0 90 0 1 0 91 0 1 0 92 0 1 0 93 0 1 0 94 0 1 0 95 0 1 0 96 0 1 0 97 0 1 0 98 0 1 0 99 0 1 0 100 0 1 0 101 0 0 1 102 0 0 1 103 0 0 1 104 0 0 1 105 0 0 1 106 0 0 1 107 0 0 1 108 0 0 1 109 0 0 1 110 0 0 1 111 0 0 1 112 0 0 1 113 0 0 1 114 0 0 1 115 0 0 1 116 0 0 1 117 0 0 1 118 0 0 1 119 0 0 1 120 0 0 1 121 0 0 1 122 0 0 1 123 0 0 1 124 0 0 1 125 0 0 1 126 0 0 1 127 0 0 1 128 0 0 1 129 0 0 1 130 0 0 1 131 0 0 1 132 0 0 1 133 0 0 1 134 0 0 1 135 0 0 1 136 0 0 1 137 0 0 1 138 0 0 1 139 0 0 1 140 0 0 1 141 0 0 1 142 0 0 1 143 0 0 1 144 0 0 1 145 0 0 1 146 0 0 1 147 0 0 1 148 0 0 1 149 0 0 1 150 0 0 1
fuente
Yo uso una función de este tipo (para data.table):
# Ta funkcja dla obiektu data.table i zmiennej var.name typu factor tworzy dummy variables o nazwach "var.name: (level1)" factorToDummy <- function(dtable, var.name){ stopifnot(is.data.table(dtable)) stopifnot(var.name %in% names(dtable)) stopifnot(is.factor(dtable[, get(var.name)])) dtable[, paste0(var.name,": ",levels(get(var.name)))] -> new.names dtable[, (new.names) := transpose(lapply(get(var.name), FUN = function(x){x == levels(get(var.name))})) ] cat(paste("\nDodano zmienne dummy: ", paste0(new.names, collapse = ", "))) }
Uso:
data <- data.table(data) data[, x:= droplevels(x)] factorToDummy(data, "x")
fuente
otra forma de hacerlo es usar
ifelse(year < 1965 , 1, 0)
fuente
Hola, escribí esta función general para generar una variable ficticia que esencialmente replica la función de reemplazo en Stata.
Si x es, el marco de datos es x y quiero una variable ficticia llamada
a
que tomará valor1
cuandox$b
tome valorc
introducedummy<-function(x,a,b,c){ g<-c(a,b,c) n<-nrow(x) newcol<-g[1] p<-colnames(x) p2<-c(p,newcol) new1<-numeric(n) state<-x[,g[2]] interest<-g[3] for(i in 1:n){ if(state[i]==interest){ new1[i]=1 } else{ new1[i]=0 } } x$added<-new1 colnames(x)<-p2 x }
fuente
También podemos usar
cSplit_e
fromsplitstackshape
. Usando los datos de @ zx8754df1 <- data.frame(id = 1:4, year = 1991:1994) splitstackshape::cSplit_e(df1, "year", fill = 0) # id year year_1 year_2 year_3 year_4 #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
Para hacer que funcione para datos que no sean numéricos necesidad que especificar
type
como"character"
explícitamentedf1 <- data.frame(id = 1:4, let = LETTERS[1:4]) splitstackshape::cSplit_e(df1, "let", fill = 0, type = "character") # id let let_A let_B let_C let_D #1 1 A 1 0 0 0 #2 2 B 0 1 0 0 #3 3 C 0 0 1 0 #4 4 D 0 0 0 1
fuente