Переместить одинаковые уровни факторов в разных столбцах в один и тот же столбец в R

У меня есть датафрейм с разными переменными, которые могут иметь несколько уровней факторов:

      id     tag_1      tag_2      tag_3
1:    3      human      NA         artist
2:    5      human      NA         NA
3:    7      song       artist     human
4:    8      town       human      NA   

Как вы можете видеть, "человеческий" уровень присутствует в трех разных переменных (tag_1, tag_2 и tag_3), а уровень "artist" в двух переменных (tag_2 и tag_3).

Зная, что каждый уровень факторов уникален в данной строке, я хотел бы сгруппировать одинаковые уровни в один и тот же столбец, чтобы в каждом столбце были исключительные уровни факторов:

      id     tag_1      tag_2      tag_3
1:    3      human      NA         artist
2:    5      human      NA         NA
3:    7      human      song       artist
4:    8      human      town       NA  

Есть ли способ сделать это?

Если нет, альтернативой было бы отсортировать в каждой строке уровни по вхождениям (вхождениям во всех данных)...

Спасибо за любую блестящую идею!

1 ответ

Я бы сделал что-то вроде этого:

library(data.table)
melt(setDT(mydf), "id", na.rm = TRUE)[
  , dcast(.SD, id ~ value, value.var = "value")]
#    id artist human song town
# 1:  3 artist human   NA   NA
# 2:  5     NA human   NA   NA
# 3:  7 artist human song   NA
# 4:  8     NA human   NA town

Оттуда легко переименовать столбцы, если вам действительно нужно, чтобы они были в формате "tag_number".

Или просто создайте двоичный индикатор:

melt(setDT(mydf), "id", na.rm = TRUE)[
  , dcast(.SD, id ~ value, value.var = "variable", fun = length, fill = 0)]
#    id artist human song town
# 1:  3      1     1    0    0
# 2:  5      0     1    0    0
# 3:  7      1     1    1    0
# 4:  8      0     1    0    1

Параллели в "тидиверсе" будут:

library(tidyverse)
mydf %>% 
  gather(key, val, -id, na.rm = TRUE) %>% 
  select(-key) %>% 
  spread(val, val)

mydf %>% 
  gather(key, val, -id, na.rm = TRUE) %>% 
  select(-key) %>% 
  mutate(value = 1) %>% 
  spread(val, value, fill = 0)
Другие вопросы по тегам