Search code examples
rdataframedplyrdata.tableplyr

Alternative to plyr::mapvalues in data.table


I am looking for a readable alternative to plyr::mapvalues in data.table.

For example, in plyr::mapvalues, if I would like to change the values of carb in mtcars to type1, type2, type3, I would do something like this:

library(tidyverse)

mtcars %>% 
  mutate(carb = plyr::mapvalues(
    carb,
    from = c("1", "2", "3", "4", "6", "8"),
    to = c("type1", "type1", "type2", "type2", "type3", "type3")))

To get the same thing in data.table, I would do it like this, which doesn't seem to be the conventional method:

library(data.table)

dt <- data.table(mtcars)
dt$carb <- as.character(dt$carb)

dt[which(carb %in% c("1", "2")), 
   carb := "type1"]

dt[which(carb %in% c("3", "4")), 
   carb := "type2"]

dt[which(carb %in% c("6", "8")), 
   carb := "type3"]

Is it possible to change all the values in one condition (dt[...])?


Solution

  • Using base::factor is the easiest method:

    library(data.table)
    
    setDT(mtcars)[, carb := factor(carb, 
                                    levels = c("1", "2", "3", 
                                               "4", "6", "8"),
                                    labels = c("type1", "type1",
                                               "type2", "type2", 
                                               "type3", "type3"))][]
    
    #>      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
    #>  1: 21.0   6 160.0 110 3.90 2.620 16.46  0  1    4 type2
    #>  2: 21.0   6 160.0 110 3.90 2.875 17.02  0  1    4 type2
    #>  3: 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4 type1
    #>  4: 21.4   6 258.0 110 3.08 3.215 19.44  1  0    3 type1
    #>  5: 18.7   8 360.0 175 3.15 3.440 17.02  0  0    3 type1
    #>  6: 18.1   6 225.0 105 2.76 3.460 20.22  1  0    3 type1
    #>  7: 14.3   8 360.0 245 3.21 3.570 15.84  0  0    3 type2
    #>  8: 24.4   4 146.7  62 3.69 3.190 20.00  1  0    4 type1
    #>  9: 22.8   4 140.8  95 3.92 3.150 22.90  1  0    4 type1
    ## ...