Home > database >  Split variable into new column variable for each factor
Split variable into new column variable for each factor

Time:09-06

Using the R dataset mtcars, I want to make a new binary variable for each level of the "cyl" variable.

For example, the values of cyl are 6, 4, and 8.

I want a new dataset with variables "cyl_4", "cyl_6", and "cyl_8" equal to 1 when each of these numbers occur.

Am looking for solutions that create a new variable for each level of the original variable.

Have:

                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

Want:

                   mpg cyl disp  hp drat    wt  qsec vs am gear carb cyl_4 cyl_6 cyl_8
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4 0     1      0
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4 0     1      0
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1 1     0      0
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1 0     1      0
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2 0     0      1
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1 0     1      0

CodePudding user response:

Here's one tidyverse solution: pivot on the cyl column, then replace the values in the 3 resulting columns with 0 where they are NA, otherwise with 1.

library(dplyr)
library(tidyr)
library(tibble)

mtcars %>% 
  rownames_to_column(var = "model") %>% 
  pivot_wider(names_from = "cyl", 
              values_from = "cyl", 
              names_prefix = "cyl_", 
              names_sort = TRUE) %>% 
  mutate(across(starts_with("cyl"), ~ ifelse(is.na(.), 0, 1)))

Result (first 5 rows):

# A tibble: 32 × 14
   model               mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb cyl_4 cyl_6 cyl_8
   <chr>             <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 Mazda RX4          21    160    110  3.9   2.62  16.5     0     1     4     4     0     1     0
 2 Mazda RX4 Wag      21    160    110  3.9   2.88  17.0     0     1     4     4     0     1     0
 3 Datsun 710         22.8  108     93  3.85  2.32  18.6     1     1     4     1     1     0     0
 4 Hornet 4 Drive     21.4  258    110  3.08  3.22  19.4     1     0     3     1     0     1     0
 5 Hornet Sportabout  18.7  360    175  3.15  3.44  17.0     0     0     3     2     0     0     1

CodePudding user response:

You could use model.matrix() to create the design matrix for a catogorical variable.

cbind(mtcars, model.matrix(~ cyl - 1, transform(mtcars, cyl = as.factor(cyl))))

#                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb cyl4 cyl6 cyl8
# Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4    0    1    0
# Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4    0    1    0
# Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1    1    0    0
# Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1    0    1    0
# Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2    0    0    1
# Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1    0    1    0
  • Related