with variable regresion generar funcion from dummy_cols dummy dummies create con cols categorical r r-faq

generar - regresion con variables dummy en r



Generar una variable ficticia (15)

Convierte tus datos a data.table y usa set por referencia y filtro de fila

library(data.table) dt <- as.data.table(your.dataframe.or.whatever) dt[, is.1957 := 0] dt[year == 1957, is.1957 := 1]

Ejemplo de juguete con 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]

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:

  1. ¿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)?

  2. ¿Cómo puedo generar una variable ficticia que sea cero antes de 1957 y tome el valor 1 desde 1957 en adelante hasta 2009?


El paquete mlr incluye createDummyFeatures 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 suelta la variable original. https://www.rdocumentation.org/packages/mlr/versions/2.9/topics/createDummyFeatures


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 xy quiero una variable ficticia llamada a que tomará el valor 1 cuando x$b toma valor c

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 }


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 usar 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 que quisiera usar, por ejemplo, 4 y 7, podría usar ifelse(year == 1957, 4, 7) .


La función ifelse 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 anidación ...

> 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"

Esta es la opción más directa.


Las otras respuestas aquí ofrecen rutas directas para realizar esta tarea, una que muchos modelos (por ejemplo, lm ) le harán internamente de todos modos. Sin embargo, aquí hay maneras de hacer variables ficticias con los paquetes de caret y recipes populares de Max Kuhn. Aunque algo más detallado, ambos escalan fácilmente a situaciones más complicadas, y se ajustan perfectamente en sus respectivos marcos.

caret::dummyVars

Con caret , la función relevante es dummyVars , que tiene un método de predict para aplicarlo 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 es step_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 la prep y bake o bake juice :

# 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


Lo leí 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) }


Lo que normalmente hago para trabajar con este tipo de variables ficticias es:

(1) ¿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)

data$factor_year_1 <- factor ( with ( data, ifelse ( ( year == 1957 ), 1 , 0 ) ) )

(2) ¿cómo puedo generar una variable ficticia que sea cero antes de 1957 y tome el valor 1 desde 1957 en adelante hasta 2009?

data$factor_year_2 <- factor ( with ( data, ifelse ( ( year < 1957 ), 0 , 1 ) ) )

Entonces, puedo presentar este factor como una variable ficticia en mis modelos. Por ejemplo, para ver si hay una tendencia a largo plazo en una variable y :

summary ( lm ( y ~ t, data = data ) )

¡Espero que esto ayude!


Otra forma en que puede hacerlo es usar

ifelse(year < 1965 , 1, 0)


Otra forma es usar mtabulate del paquete qdapTools , es decir,

df <- 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,

A B C 1 0 0 1 2 1 0 0 3 0 0 1 4 0 1 0 5 0 1 0


Para el caso de uso presentado en la pregunta, también puede simplemente multiplicar la condición lógica por 1 (o tal vez incluso mejor, con 1L ):

# 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:

> df1 yr is.1957 after.1957 1 1951 0 0 2 1952 0 0 3 1953 0 0 4 1954 0 0 5 1955 0 0 6 1956 0 0 7 1957 1 1 8 1958 0 1 9 1959 0 1 10 1960 0 1

Para los casos de uso presentados en, por ejemplo, las respuestas de @ zx8754 y @Sotos, todavía hay algunas otras opciones que aún no se han cubierto.

1) Haz tu propia make_dummies make_dummies

# 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:

id year y1991 y1992 y1993 y1994 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 5 5 1992 0 1 0 0

2) use la dcast dcast desde data.table o reshape2

dcast(df2, id + year ~ year, fun.aggregate = length)

lo que da:

id year 1991 1992 1993 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 5 5 1992 0 1 0 0

Sin embargo, esto no funcionará cuando haya valores duplicados en la columna para los cuales se deben crear los dummies. En el caso de que se necesite una función de agregación específica para dcast el resultado de dcast debe combinarse 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 es orden según la columna by ):

var A B C 1 A 1 0 0 2 B 0 1 0 3 B 0 1 0 4 C 0 0 1 5 C 0 0 1

3) usa la función de tidyr de tidyr (con dplyr de dplyr )

library(dplyr) library(tidyr) df2 %>% mutate(v = 1, yr = year) %>% spread(yr, v, fill = 0)

lo que da:

id year 1991 1992 1993 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 5 5 1992 0 1 0 0


Si desea obtener K variables ficticias, en lugar de K-1, intente:

dummies = table(1:length(year),as.factor(year))

Mejor,


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


Yo uso tal función (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")


Otra opción que puede funcionar mejor si tiene muchas variables es factor y model.matrix .

> year.f = factor(year) > dummies = model.matrix(~year.f)

Esto incluirá una columna de intercepción (todas) y una columna para cada uno de los años en su conjunto de datos excepto uno, que será el valor "predeterminado" o de intercepción.

Puede cambiar cómo se elige el "predeterminado" jugando con contrasts.arg en model.matrix .

Además, si desea omitir la intercepción, puede simplemente colocar la primera columna o agregar +0 al final de la fórmula.

Espero que esto sea útil.