Generieren Sie eine Dummy-Variable


84

Ich habe Probleme beim Generieren der folgenden Dummy-Variablen in R:

Ich analysiere jährliche Zeitreihendaten (Zeitraum 1948-2009). Ich habe zwei Fragen:

  1. Wie generiere ich eine Dummy-Variable für Beobachtung Nr. 10, dh für das Jahr 1957 (Wert = 1 bei 1957 und sonst Null)?

  2. Wie generiere ich eine Dummy-Variable, die vor 1957 Null ist und von 1957 bis 2009 den Wert 1 annimmt?

Antworten:


110

Eine andere Option, die besser funktionieren kann, wenn Sie viele Variablen haben, ist factorund model.matrix.

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

Dies umfasst eine Intercept-Spalte (alle) und eine Spalte für jedes der Jahre in Ihrem Datensatz, mit Ausnahme einer Spalte, die der "Standard" - oder Intercept-Wert ist.

Sie können ändern, wie die "Standardeinstellung" ausgewählt wird, indem Sie mit contrasts.argin herumspielen model.matrix.

Wenn Sie den Achsenabschnitt weglassen möchten, können Sie einfach die erste Spalte löschen oder +0am Ende der Formel hinzufügen .

Hoffe das ist nützlich.


4
Was ist, wenn Sie Dummy-Variablen für alle (anstelle von k-1) ohne Intercept generieren möchten?
Fernando Hoces De La Guardia

1
Beachten Sie, dass model.matrix () mehrere Variablen akzeptiert, um sie in Dummies umzuwandeln: model.matrix (~ var1 + var2, data = df) Stellen Sie erneut sicher, dass es sich um Faktoren handelt.
Slizb

3
@ Synergist-Tabelle (1: n, Faktor). Wobei Faktor die ursprüngliche Variable und n ihre Länge ist
Fernando Hoces De La Guardia

1
@ Synergist diese Tabelle ist Anxk-Matrix mit allen k Indikatorvariablen (anstelle von k-1)
Fernando Hoces De La Guardia

6
@FernandoHocesDeLaGuardia Sie können den Achsenabschnitt entweder mit + 0 oder aus einer Formel entfernen - 1. So model.matrix(~ year.f + 0)wird ein Geben Dummy - Variablen ohne Referenzebene geben.
Gregor Thomas

59

Der einfachste Weg, diese Dummy-Variablen zu erzeugen, ist etwa der folgende:

> 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

Im Allgemeinen können Sie ifelseabhängig von einer Bedingung zwischen zwei Werten wählen. Wenn Sie also anstelle einer 0-1-Dummy-Variablen aus irgendeinem Grund beispielsweise 4 und 7 verwenden möchten, können Sie diese verwenden ifelse(year == 1957, 4, 7).


48

Verwenden von 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

Vielleicht kann das Hinzufügen von "fun = factor" im Funktionsdummy helfen, wenn dies die Bedeutung der Variablen ist.
Filippo Mazza

@FilippoMazza Ich bevorzuge es, sie als Ganzzahl zu behalten, ja, wir könnten bei Bedarf einen Faktor festlegen.
zx8754

Wie entfernst du df1 vor den Namen der einzelnen Dummy-Spaltenüberschriften?
Mike

@mike colnames (df1) <- gsub ("df1_", "", fixed = TRUE, colnames (df1))
zx8754

19

Das Paket mlrenthält createDummyFeatureszu diesem Zweck:

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 löscht die ursprüngliche Variable.

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


1
Enrique, ich habe versucht, das Paket zu installieren, aber es scheint nach dem Ausführen der Bibliothek (mlr) nicht zu funktionieren. Ich erhalte die folgende Fehlermeldung: «Fehler im loadNamespace (j <- i [[1L]], c (lib.loc, .libPaths ()), versionCheck = vI [[j]]): Es gibt kein Paket mit dem Namen 'ggvis 'Zusätzlich: Warnmeldung: Paket' mlr 'wurde unter R Version 3.2.5 erstellt. Fehler: Paket- oder Namespace-Laden für' mlr 'fehlgeschlagen »
Ein alter Mann im Meer.

1
Sie müssen zuerst 'ggvis' installieren
Ted Mosby

17

Die anderen Antworten hier bieten direkte Wege, um diese Aufgabe zu erfüllen - eine, die viele Modelle (z. B. lm) ohnehin intern für Sie erledigen. Dennoch gibt es hier Möglichkeiten, Dummy-Variablen mit Max Kuhns beliebten Paketen caretund recipesPaketen zu erstellen. Obwohl sie etwas ausführlicher sind, lassen sich beide leicht auf kompliziertere Situationen skalieren und passen genau in ihre jeweiligen Rahmenbedingungen.


caret::dummyVars

Mit caretist die relevante Funktion dummyVars, die eine predictMethode hat, um sie auf einen Datenrahmen anzuwenden:

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

Mit recipesist die relevante Funktion 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

Extrahieren Sie die Daten je nach Kontext mit prepund entweder bakeoder 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

11

Für den in der Frage dargestellten Anwendungsfall können Sie die logische Bedingung auch einfach mit 1(oder vielleicht sogar besser mit 1L) multiplizieren :

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

was gibt:

> 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

Für die Anwendungsfälle, wie sie beispielsweise in den Antworten von @ zx8754 und @Sotos dargestellt sind, gibt es noch einige andere Optionen, die imo noch nicht behandelt wurden.

1) Machen Sie Ihre eigenen make_dummies-function

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

was gibt:

  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) Verwenden Sie die Funktion dcastvon entweder oder

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

was gibt:

  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

Dies funktioniert jedoch nicht, wenn die Spalte, für die die Dummies erstellt werden müssen, doppelte Werte enthält. In dem Fall, dass eine bestimmte Aggregationsfunktion benötigt wird dcastund das Ergebnis der dcastNotwendigkeit wieder mit dem Original zusammengeführt werden muss:

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

was gibt (beachten Sie, dass das Ergebnis nach der bySpalte geordnet ist ):

  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) Verwenden Sie die spread -Funktion von(mit mutatevon)

library(dplyr)
library(tidyr)

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

was gibt:

  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

10

Was ich normalerweise mache, um mit dieser Art von Dummy-Variablen zu arbeiten, ist:

(1) Wie generiere ich eine Dummy-Variable für Beobachtung Nr. 10, dh für das Jahr 1957 (Wert = 1 bei 1957 und ansonsten Null)?

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

(2) Wie generiere ich eine Dummy-Variable, die vor 1957 Null ist und von 1957 bis 2009 den Wert 1 annimmt?

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

Dann kann ich diesen Faktor als Dummy-Variable in meine Modelle einführen. Um beispielsweise zu sehen, ob eine Variable einen langfristigen Trend aufweist y :

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

Hoffe das hilft!


7

Wenn Sie anstelle von K-1 K-Dummy-Variablen erhalten möchten, versuchen Sie Folgendes:

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

Beste,


Die resultierende Tabelle kann nicht als data.frame verwendet werden. Wenn das ein Problem ist, verwenden Sie as.data.frame.matrix(dummies), um es in eines zu übersetzen
sheß

7

Ich habe das im Kaggle-Forum gelesen:

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

5

Die ifelseFunktion eignet sich am besten für eine einfache Logik wie diese.

> 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

Wenn Sie möchten, dass Zeichendaten zurückgegeben werden, können Sie dies auch tun.

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

Kategoriale Variablen mit Verschachtelung ...

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

Dies ist die einfachste Option.


4

Eine andere Möglichkeit ist die Verwendung mtabulateaus dem qdapToolsPaket, dh

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)

was gibt,

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

2

Konvertieren Sie Ihre Daten in eine data.table und verwenden Sie set by reference und row filter

library(data.table)

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

Proof-of-Concept-Spielzeugbeispiel:

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]

2

Dieser eine Liner in Basis R.

model.matrix( ~ iris$Species - 1)

gibt

    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

1

Ich benutze eine solche Funktion (für 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 = ", ")))
}

Verwendung:

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

1

Eine andere Möglichkeit ist die Verwendung

ifelse(year < 1965 , 1, 0)

0

Hallo, ich habe diese allgemeine Funktion geschrieben, um eine Dummy-Variable zu generieren, die im Wesentlichen die Ersetzungsfunktion in Stata repliziert.

Wenn x ist, ist der Datenrahmen x und ich möchte eine Dummy-Variable namens a, die Wert annimmt, 1wenn x$bWert angenommen wirdc

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
  }

0

Wir können auch cSplit_evon verwenden splitstackshape. Verwenden der Daten von @ zx8754

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

Um es für andere Daten als numerisch wir müssen arbeiten , um anzugeben , typewie "character"ausdrücklich

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.