Buat variabel dummy

87

Saya mengalami masalah dalam membuat variabel dummy berikut di R:

Saya menganalisis data deret waktu tahunan (periode waktu 1948-2009). Saya punya dua pertanyaan:

  1. Bagaimana cara menghasilkan variabel dummy untuk observasi # 10, yaitu untuk tahun 1957 (nilai = 1 pada 1957 dan nol sebaliknya)?

  2. Bagaimana cara membuat variabel dummy yang nol sebelum 1957 dan mengambil nilai 1 dari 1957 dan seterusnya hingga 2009?

Pantera
sumber

Jawaban:

113

Opsi lain yang dapat bekerja lebih baik jika Anda memiliki banyak variabel adalah factordan model.matrix.

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

Ini akan menyertakan kolom intersep (semua satu) dan satu kolom untuk setiap tahun dalam kumpulan data Anda kecuali satu, yang akan menjadi nilai "default" atau intersep.

Anda dapat mengubah bagaimana "default" dipilih dengan mengotak-atik contrasts.argdi model.matrix.

Selain itu, jika Anda ingin menghilangkan intersep, Anda bisa melepas kolom pertama atau menambahkan +0ke akhir rumus.

Semoga bermanfaat.

David J. Harris
sumber
4
bagaimana jika Anda ingin menghasilkan variabel dummy untuk semua (bukan k-1) tanpa intercept?
Fernando Hoces De La Guardia
1
perhatikan bahwa model.matrix () menerima beberapa variabel untuk diubah menjadi dummies: model.matrix (~ var1 + var2, data = df) Sekali lagi, pastikan bahwa variabel tersebut adalah faktor.
slizb
3
@ Tabel Sinergist (1: n, faktor). Di mana faktor adalah variabel asli dan n adalah panjangnya
Fernando Hoces De La Guardia
1
@ Sinergist bahwa tabel adalah matriks anxk dengan semua variabel indikator k (bukan k-1)
Fernando Hoces De La Guardia
6
@FernandoHocesDeLaGuardia Anda dapat menghapus penyadapan dari rumus baik dengan + 0 atau - 1. Jadi model.matrix(~ year.f + 0)akan memberikan variabel dummy yang diberikan tanpa tingkat referensi.
Gregor Thomas
60

Cara paling sederhana untuk menghasilkan variabel dummy ini adalah seperti berikut:

> 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

Secara lebih umum, Anda dapat menggunakan ifelseuntuk memilih di antara dua nilai bergantung pada suatu kondisi. Jadi jika alih-alih variabel dummy 0-1, karena alasan tertentu Anda ingin menggunakan, katakanlah, 4 dan 7, Anda dapat menggunakan ifelse(year == 1957, 4, 7).

Martin O'Leary
sumber
49

Menggunakan 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
zx8754
sumber
Mungkin menambahkan "fun = factor" dalam function dummy dapat membantu jika itu adalah arti dari variabel tersebut.
Filippo Mazza
@FilippoMazza Saya lebih suka menyimpannya sebagai integer, ya, kami bisa mengatur faktor jika diperlukan.
zx8754
bagaimana Anda menghapus df1 sebelum setiap nama header kolom dummy?
mikropon
1
@mike colnames (df1) <- gsub ("df1_", "", fixed = TRUE, colnames (df1))
zx8754
19

Paket mlrtermasuk createDummyFeaturesuntuk tujuan ini:

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 menjatuhkan variabel asli.

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

Enrique Pérez Herrero
sumber
1
Enrique, saya sudah mencoba menginstal paket, tetapi sepertinya tidak berfungsi setelah melakukan library (mlr). Saya mendapatkan kesalahan berikut: «Kesalahan dalam loadNamespace (j <- i [[1L]], c (lib.loc, .libPaths ()), versionCheck = vI [[j]]): tidak ada paket yang disebut 'ggvis 'Selain itu: Pesan peringatan: paket' mlr 'dibangun di bawah R versi 3.2.5 Kesalahan: pemuatan paket atau namespace gagal untuk' mlr '»
Orang tua di laut.
1
Anda perlu menginstal 'ggvis' terlebih dahulu
Ted Mosby
17

Jawaban lain di sini menawarkan rute langsung untuk menyelesaikan tugas ini — yang lmakan dilakukan oleh banyak model (misalnya ) secara internal untuk Anda. Meskipun demikian, berikut adalah cara untuk membuat variabel dummy dengan paket caretdan populer Max Kuhn recipes. Meskipun agak lebih bertele-tele, keduanya dapat diskalakan dengan mudah ke situasi yang lebih rumit, dan cocok dengan kerangka kerja masing-masing.


caret::dummyVars

Dengan caret, fungsi yang relevan adalah dummyVars, yang memiliki predictmetode untuk mengaplikasikannya pada data frame:

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

Dengan recipes, fungsi yang relevan adalah 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

Bergantung pada konteks, ekstrak data dengan prepdan salah satu bakeatau 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
alistaire
sumber
11

Untuk kasus penggunaan seperti yang disajikan dalam pertanyaan, Anda juga dapat mengalikan kondisi logis dengan 1(atau mungkin lebih baik, dengan 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)

pemberian yang mana:

> 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

Untuk usecases seperti yang disajikan dalam contoh jawaban dari @ zx8754 dan @Sotos, masih ada beberapa opsi lain yang belum dibahas imo.

1) Buat make_dummiesfungsi Anda sendiri

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

pemberian yang mana:

  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) gunakan dcast-fungsi dari keduanya atau

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

pemberian yang mana:

  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

Namun, ini tidak akan berfungsi ketika ada nilai duplikat di kolom yang harus dibuat boneka. Dalam kasus fungsi agregasi khusus diperlukan untuk dcastdan hasil dari dcastkebutuhan untuk digabungkan kembali ke aslinya:

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

yang memberi (perhatikan bahwa hasilnya diurutkan menurut bykolom):

  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) gunakan spread-fungsi dari(dengan mutatedari)

library(dplyr)
library(tidyr)

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

pemberian yang mana:

  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
Jaap
sumber
10

Apa yang biasanya saya lakukan untuk bekerja dengan variabel dummy semacam ini adalah:

(1) bagaimana cara menghasilkan variabel dummy untuk observasi # 10, yaitu untuk tahun 1957 (nilai = 1 pada 1957 dan nol sebaliknya)

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

(2) bagaimana cara menghasilkan variabel dummy yang nol sebelum 1957 dan mengambil nilai 1 dari 1957 dan seterusnya hingga 2009?

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

Kemudian, saya dapat memperkenalkan faktor ini sebagai variabel dummy dalam model saya. Misalnya, untuk melihat apakah ada tren jangka panjang dalam suatu variabel y :

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

Semoga ini membantu!

Ricardo González-Gil
sumber
7

Jika Anda ingin mendapatkan variabel dummy K, alih-alih K-1, coba:

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

Terbaik,

Fernando Hoces De La Guardia
sumber
tabel yang dihasilkan tidak dapat digunakan sebagai data.frame. Jika itu masalah, gunakan as.data.frame.matrix(dummies)untuk menerjemahkannya menjadi satu
sheß
7

Saya membaca ini di forum 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)
}
skpro19
sumber
5

The ifelseFungsi yang terbaik untuk logika sederhana seperti ini.

> 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

Juga, jika Anda ingin mengembalikan data karakter maka Anda dapat melakukannya.

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

Variabel kategori dengan penumpukan ...

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

Ini adalah opsi paling mudah.

Alex Thompson
sumber
5

Cara lain adalah dengan menggunakan mtabulatefrom qdapToolspackage, yaitu

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)

pemberian yang mana,

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

Liner yang satu ini di basis R

model.matrix( ~ iris$Species - 1)

memberi

    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
stevec
sumber
2

Ubah data Anda menjadi data.table dan gunakan set by reference dan row filtering

library(data.table)

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

Contoh mainan bukti konsep:

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]
kata-kata
sumber
1

Saya menggunakan fungsi seperti itu (untuk 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 = ", ")))
}

Pemakaian:

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

cara lain yang bisa Anda lakukan adalah menggunakan

ifelse(year < 1965 , 1, 0)
Sophia J.
sumber
0

Hai saya menulis fungsi umum ini untuk menghasilkan variabel dummy yang pada dasarnya mereplikasi fungsi ganti di Stata.

Jika x adalah kerangka data adalah x dan saya ingin variabel dummy disebut ayang akan mengambil nilai 1saat x$bmengambil nilaic

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
  }
kangkan Dc
sumber
0

Kami juga dapat menggunakan cSplit_edari splitstackshape. Menggunakan data @ 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

Untuk membuatnya bekerja untuk data selain numerik kita perlu menentukan typesebagai "character"eksplisit

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
Ronak Shah
sumber