Bir kukla değişken oluşturun


87

R'de aşağıdaki kukla değişkenleri oluştururken sorun yaşıyorum:

Yıllık zaman serisi verilerini analiz ediyorum (1948-2009 dönemi). İki sorum var:

  1. Gözlem # 10 için, yani 1957 yılı için (değer = 1957'de 1 ve aksi takdirde sıfır) bir kukla değişken nasıl üretebilirim?

  2. 1957'den önce sıfır olan ve 1957'den 2009'a kadar 1 değerini alan bir kukla değişken nasıl üretebilirim?

Yanıtlar:


113

Birçok değişkeniniz varsa daha iyi çalışabilecek başka bir seçenek de factorve model.matrix.

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

Bu, bir kesme sütunu (tümü) ve "varsayılan" veya kesme değeri olan biri hariç, veri kümenizdeki her yıl için bir sütun içerir.

Sen "varsayılan" karıştırmasını tarafından nasıl seçildiği değiştirebilir contrasts.argiçinde model.matrix.

Ayrıca, kesmeyi atlamak istiyorsanız, ilk sütunu bırakabilir veya +0formülün sonuna ekleyebilirsiniz .

Umarım bu yararlıdır.


4
hepsi için (k-1 yerine) kesişimsiz kukla değişkenler oluşturmak istiyorsanız ne olur?
Fernando Hoces De La Guardia

1
model.matrix () 'in birden çok değişkeni kukla modellere dönüştürmek için kabul ettiğini unutmayın: model.matrix (~ var1 + var2, data = df) Yine, bunların faktör olduklarından emin olun.
slizb

3
@Synergist tablosu (1: n, faktör). Faktörün orijinal değişken ve n'nin uzunluğu olduğu yerde
Fernando Hoces De La Guardia

1
@Synergist bu tablo, tüm k gösterge değişkenlerini içeren anxk matrisidir (k-1 yerine)
Fernando Hoces De La Guardia 3'15

6
@FernandoHocesDeLaGuardia Sen ile ya bir formülden kesenini kaldırabilir + 0 veya - 1. Bu nedenle model.matrix(~ year.f + 0), referans seviyesi olmayan bir verelim kukla değişkenler.
Gregor Thomas

60

Bu kukla değişkenleri üretmenin en basit yolu şuna benzer bir şeydir:

> 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

Daha genel ifelseolarak, bir koşula bağlı olarak iki değer arasından seçim yapmak için kullanabilirsiniz . Yani, 0-1 kukla değişken yerine, herhangi bir nedenle, örneğin 4 ve 7'yi kullanmak istediyseniz, kullanabilirsiniz ifelse(year == 1957, 4, 7).


49

Dummies kullanma :: 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

Değişkenin anlamı buysa, belki işlev kukla içine "eğlence = faktör" eklemek yardımcı olabilir.
Filippo Mazza 08

@FilippoMazza Onları tam sayı olarak tutmayı tercih ediyorum, evet, gerekirse faktör belirleyebiliriz.
zx8754

her boş sütun başlığı adından önce df1'i nasıl kaldırırsınız?
mike

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

19

Paket bu amaçla mlrşunları içerir createDummyFeatures:

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 orijinal değişkeni düşürür.

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


1
Enrique, paketi yüklemeyi denedim, ancak kitaplık (mlr) yaptıktan sonra çalışmıyor gibi görünüyor. Şu hatayı alıyorum: «LoadNamespace'de hata (j <- i [[1L]], c (lib.loc, .libPaths ()), versionCheck = vI [[j]]): 'ggvis adında bir paket yok 'Ek olarak: Uyarı iletisi:' mlr 'paketi R sürüm 3.2.5 altında oluşturuldu Hata:' mlr 'için paket veya ad alanı yüklemesi başarısız oldu »
Denizde yaşlı bir adam.

1
önce 'ggvis'i yüklemeniz gerekiyor
Ted Mosby

17

Buradaki diğer cevaplar, bu görevi yerine getirmek için doğrudan yollar sunar - bir çok modelin (örneğin lm) dahili olarak sizin için yapacağı bir tanesi . Yine de, işte Max Kuhn'un popüler caretve recipespaketleriyle kukla değişkenler yapmanın yolları . Biraz daha ayrıntılı olsalar da, her ikisi de daha karmaşık durumlara kolayca ölçeklenir ve kendi çerçevelerine düzgün bir şekilde uyar.


caret::dummyVars

İle caretilgili işlev, onu bir veri çerçevesine uygulamak için dummyVarsbir predictyönteme sahiptir :

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

İle recipesilgili işlev 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

Bağlama bağlı olarak, verileri veya aşağıdakilerden prepbiriyle çıkarın :bakejuice

# 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

Soruda sunulan kullanım senaryosu için, mantıksal koşulu şununla 1(veya daha da iyisi ile 1L) çarpabilirsiniz :

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

hangi verir:

> 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

Örneğin @ zx8754 ve @Sotos'ta sunulan kullanım durumları için, imo henüz ele alınmamış başka seçenekler de var.

1) Kendi make_dummiesişlevinizi yapı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'))

hangi verir:

  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) dcasther ikisinden de- işlevini kullanın veya

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

hangi verir:

  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

Bununla birlikte, kukla değerlerin oluşturulması gereken sütunda yinelenen değerler olduğunda bu işe yaramayacaktır. Belirli bir toplama işlevine ihtiyaç duyulması dcastve sonucunun dcastorijinalle birleştirilmesi gerekmesi durumunda:

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

(sonucun bysütuna göre sıralandığına dikkat edin ):

  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) spreadişlevini kullanınile ( mutatedan)

library(dplyr)
library(tidyr)

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

hangi verir:

  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

Normalde bu tür kukla değişkenlerle çalışmak için yaptığım şey:

(1) 10 numaralı gözlem için bir kukla değişken nasıl üretirim, yani 1957 yılı için (değer = 1957'de 1 ve aksi takdirde sıfır)

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

(2) 1957'den önce sıfır olan ve 1957'den 2009'a kadar 1 değerini alan bir kukla değişkeni nasıl oluşturabilirim?

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

Daha sonra bu faktörü modellerimde kukla değişken olarak tanıtabilirim. Örneğin, değişkenlerde uzun vadeli bir eğilim olup olmadığını görmek için y :

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

Bu yardımcı olur umarım!


7

K-1 yerine K kukla değişkenler almak istiyorsanız şunu deneyin:

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

En iyi,


ortaya çıkan tablo data.frame olarak kullanılamaz. Bu bir sorunsa, as.data.frame.matrix(dummies)onu birine çevirmek için kullanın
sheß

7

Bunu kaggle forumunda okudum:

#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

ifelseİşlevi aşağıdaki gibi basit mantık için en iyisidir.

> 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

Ayrıca, karakter verilerini döndürmesini istiyorsanız, bunu yapabilirsiniz.

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

İç içe geçmiş kategorik değişkenler ...

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

Bu en basit seçenektir.


5

Diğer bir yolu kullanımı için mtabulategelen qdapToolspaketin, yani

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)

hangi verir

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

3

Bu R üssündeki tek astar

model.matrix( ~ iris$Species - 1)

verir

    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

2

Verilerinizi data.table'a dönüştürün ve referans ve satır filtrelemeye göre kümeyi kullanın

library(data.table)

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

Konsept kanıtı oyuncak örneği:

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]

1

Böyle bir işlev kullanıyorum (data.table için):

# 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 = ", ")))
}

Kullanım:

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

1

bunu yapmanın başka bir yolu kullanmaktır

ifelse(year < 1965 , 1, 0)

0

Merhaba, bu genel işlevi, esasen Stata'daki değiştirme işlevini kopyalayan bir kukla değişken oluşturmak için yazdım.

Veri çerçevesi x ise ve adeğeri alacak olan adında bir kukla değişken istiyorum1 zaman x$bdeğerini alırc

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

Biz de kullanabilirsiniz cSplit_egelen splitstackshape. @ Zx8754 verilerini kullanma

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

O belirtmek için sayısal biz ihtiyacı dışındaki veriler için çalışmasını sağlamak için typeolarak "character"açıkça

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.