0

If I have a the following df

id tiger donkey turtle
1 1 0 0
2 0 1 0
3 0 0 1

So that 1 equals True and 0 equals False.

And I want to create the following df

id animal
1 tiger
2 donkey
3 turtle

How would I do this using dplyr? I first thought that I could use pivot_long() but I should not have more rows after the operation.

  • You can find responses here: https://stackoverflow.com/questions/49130366/reconstruct-a-categorical-variable-from-dummies-in-r – Ruam Pimentel Apr 07 '22 at 16:10
  • More responses here: https://stackoverflow.com/questions/42036652/using-dplyr-to-gather-dummy-variables. and here: https://stackoverflow.com/questions/30333401/convert-various-dummy-logical-variables-into-a-single-categorical-variable-facto – Ruam Pimentel Apr 07 '22 at 16:11
  • @RuamPimentel good finds. Most of those are either (a) `melt` (ala the reshape suggestion in my answer) or (b) using the outdated `tidyr::gather`. I suspect there are other dupes of this, as is it a common-enough question. I'm happy closing it as a dupe if there's a better one out there that includes relatively recent `tidyr` solutions (as `dplyr`-alone is not a great method for this). – r2evans Apr 07 '22 at 16:17
  • 1
    Uhum. I agree with you @r2evans that they are showing some outdated options. I would suggest updating the answer on those posts instead of starting a new one here because they have already nice discussions there. But I’m not sure what is the best take. Given you have way more experience than me on SO, I leave to you to decide. – Ruam Pimentel Apr 07 '22 at 16:30

1 Answers1

2

dplyr

library(dplyr)
library(tidyr) # pivot_longer
pivot_longer(dat, -id, names_to = "animal") %>%
  filter(value > 0)
# # A tibble: 3 x 3
#      id animal value
#   <int> <chr>  <int>
# 1     1 tiger      1
# 2     2 donkey     1
# 3     3 turtle     1

base plus reshape2

subset(
  reshape2::melt(dat, id.vars = "id", variable.name = "animal"),
  value > 0)
r2evans
  • 141,215
  • 6
  • 77
  • 149