Search code examples
rtidyrspread

tidyr::spread but keep original data


data:

test = data.frame(case=c("cyl","eng","mon"),
worst=c(1,0,1),money=c(123,42,13),girl=c("no","yes","no"))

enter image description here

desired_test= data.frame(case=c("cyl","eng","mon"), worst=c(1,0,1),money=c(123,42,13),girl=c("no","yes","no"),
                       worst_cyl=c(1,0,0),worst_eng=c(0,0,0),worst_mon=c(0,0,1))

enter image description here

Attempt:

test %>% group_by(case) %>% spread(case,worst,fill=0,sep="_")

Why is not my attempt working?


Solution

  • I'm assuming this makes more sense in the context of a larger dataset but you can achieve the desired result by adding rowid_to_column and binding the key/value columns used in spread:

    library(tidyr)
    library(dplyr)
    
    test %>%
      rowid_to_column() %>%
      spread(case,worst,fill=0,sep="_") %>%
      cbind(test[c("case", "worst")], .) %>%
      rename_at(vars(starts_with("case_")), ~sub("case", "worst", .x)) %>%
      select(-rowid)
    
      case worst money girl worst_cyl worst_eng worst_mon
    1  cyl     1   123   no         1         0         0
    2  eng     0    42  yes         0         0         0
    3  mon     1    13   no         0         0         1