Genereer een dummy-variabele

Ik heb problemen met het genereren van de volgende dummy-variabelen in R:

Ik analyseer jaarlijkse tijdreeksgegevens (periode 1948-2009). Ik heb twee vragen:

  1. Hoe genereer ik een dummyvariabele voor observatie #10, d.w.z. voor het jaar 1957 (waarde = 1 in 1957 en anders nul)?

  2. Hoe genereer ik een dummyvariabele die vóór 1957 nul is en de waarde 1 van 1957 en later tot 2009 aanneemt?


Antwoord 1, autoriteit 100%

Een andere optie die beter werkt als je veel variabelen hebt, is factoren model.matrix.

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

Dit omvat een onderscheppingskolom (allemaal) en één kolom voor elk van de jaren in uw dataset, behalve één, wat de “standaard” of onderscheppingswaarde is.

Je kunt veranderen hoe de “standaard” wordt gekozen door te knoeien met contrasts.argin model.matrix.

Als u het snijpunt wilt weglaten, kunt u ook de eerste kolom weglaten of +0toevoegen aan het einde van de formule.

Ik hoop dat dit nuttig is.


Antwoord 2, autoriteit 52%

De eenvoudigste manier om deze dummyvariabelen te produceren is ongeveer als volgt:

> 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

Meer in het algemeen kun je ifelsegebruiken om tussen twee waarden te kiezen, afhankelijk van een voorwaarde. Dus als u in plaats van een 0-1 dummyvariabele om de een of andere reden bijvoorbeeld 4 en 7 wilt gebruiken, kunt u ifelse(year == 1957, 4, 7)gebruiken.


Antwoord 3, autoriteit 44%

dummies::dummy():

gebruiken

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

Antwoord 4, autoriteit 17%

Pakket mlrbevat createDummyFeaturesvoor dit doel:

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

createDummyFeatureslaat de originele variabele vallen.

https://www.rdocumentation.org/packages/mlr /versions/2.9/topics/createDummyFeatures
…..


Antwoord 5, autoriteit 16%

De andere antwoorden hier bieden directe routes om deze taak te volbrengen – een die veel modellen (bijv. lm) hoe dan ook intern voor u zullen doen. Desalniettemin zijn hier manieren om dummy-variabelen te maken met Max Kuhn’s populaire careten recipes-pakketten. Hoewel ze wat uitgebreider zijn, schalen ze gemakkelijk naar meer gecompliceerde situaties en passen ze netjes in hun respectieve kaders.


caret::dummyVars

Met caretis de relevante functie dummyVars, die een predictmethode heeft om deze toe te passen op een dataframe:

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

Bij recipesis de relevante functie 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

Afhankelijk van de context, extraheer de gegevens met prepen ofwel bakeof 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

Antwoord 6, Autoriteit 11%

Voor de USECase zoals gepresenteerd in de vraag, kunt u ook gewoon de logische toestand vermenigvuldigen met 1(of misschien nog beter, met 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)

wat geeft:

> 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

Voor de usecases zoals gepresenteerd in bijvoorbeeld de antwoorden van @zx8754 en @Sotos, zijn er nog enkele andere opties die imo nog niet zijn behandeld.

1) Maak je eigen make_dummies-functie

# 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'))

wat geeft:

 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) gebruik de dcast-functie van ofwel data.tableof hervorm2

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

wat geeft:

 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

Dit werkt echter niet als er dubbele waarden in de kolom staan waarvoor de dummies moeten worden gemaakt. In het geval dat een specifieke aggregatiefunctie nodig is voor dcasten het resultaat van dcastterug naar het origineel moet worden samengevoegd:

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

die geeft (merk op dat het resultaat is gerangschikt volgens de kolom 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) gebruik de spread-functie van tidyr(met mutatevan dplyr)

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

wat geeft:

 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

Antwoord 7, autoriteit 9%

Wat ik normaal gesproken doe om met dit soort dummyvariabelen te werken is:

(1) hoe genereer ik een dummyvariabele voor observatie #10, d.w.z. voor het jaar 1957 (waarde = 1 bij 1957 en anders nul)

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

(2) hoe genereer ik een dummy-variabele die vóór 1957 nul is en de waarde 1 van 1957 en later tot 2009 aanneemt?

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

Dan kan ik deze factor als dummyvariabele in mijn modellen introduceren. Om bijvoorbeeld te zien of er een langetermijntrend is in een variabele y:

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

Hopelijk helpt dit!


Antwoord 8, autoriteit 6%

Als je K dummy-variabelen wilt krijgen, in plaats van K-1, probeer dan:

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

Beste,


Antwoord 9, autoriteit 6%

Ik las dit op het Kaggle-forum:

#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)
}

Antwoord 10, autoriteit 4%

De ifelse-functie is het beste voor eenvoudige logica zoals deze.

> 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

Als u wilt dat het tekengegevens retourneert, kunt u dat ook doen.

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

Categorische variabelen met nesting…

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

Dit is de meest eenvoudige optie.


Antwoord 11, autoriteit 4%

Een andere manier is om mtabulateuit het pakket qdapToolste gebruiken, d.w.z.

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)

wat geeft,

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

Antwoord 12, autoriteit 3%

Deze oneliner in basis R

model.matrix( ~ iris$Species - 1)

geeft

   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

Antwoord 13, autoriteit 2%

Converteer uw gegevens naar een data.table en gebruik set by reference en rijfiltering

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

Proof-of-concept speelgoedvoorbeeld:

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]

Antwoord 14

Ik gebruik zo’n functie (voor 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 = ", ")))
}

Gebruik:

data <- data.table(data)
data[, x:= droplevels(x)]
factorToDummy(data, "x")

Antwoord 15

een andere manier waarop u dit kunt doen, is door

. te gebruiken

ifelse(year < 1965 , 1, 0)

Antwoord 16

We kunnen ook cSplit_evan splitstackshapegebruiken. De gegevens van @zx8754 gebruiken

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

Om het voor andere gegevens dan numerieke gegevens te laten werken, moeten we typeexpliciet specificeren als "character"

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

Antwoord 17

Hallo, ik heb deze algemene functie geschreven om een dummy-variabele te genereren die in wezen de vervangingsfunctie in Stata repliceert.

Als x het dataframe is, is x en ik wil een dummyvariabele met de naam adie waarde 1krijgt wanneer x$bwaarde 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
  }

Other episodes