Как изменить порядок этого фрейма данных?

#r #dataframe

Вопрос:

У меня есть следующий фрейм данных:

 df =structure(list(texts = c("Text 1", 
"Text 2", 
"Text 3", 
"Text 4", 
"Text 5", 
"Text 6", 
"Text 7", 
"Text 8", 
"Text 9", 
"Text 10"
), E = c(1, 0, 0, 0, 0, 0, 0, 0, 0, 0), S = c(0, 0, 0, 1, 0, 
0, 1, 0, 0, 1), G = c(0, 1, 1, 0, 1, 1, 0, 1, 1, 0)), row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10"), class = "data.frame")

     texts E S G
1   Text 1 1 0 0
2   Text 2 0 0 1
3   Text 3 0 0 1
4   Text 4 0 1 0
5   Text 5 0 0 1
6   Text 6 0 0 1
7   Text 7 0 1 0
8   Text 8 0 0 1
9   Text 9 0 0 1
10 Text 10 0 1 0

 

Как вы можете видеть сейчас, у меня есть 3 столбца (E, S, G), где 1 или 0 указывает, какой текст принадлежит какому столбцу. Что я хотел бы получить, так это следующее:

      texts Class
1   Text 1  E 
2   Text 2  G 
3   Text 3  G 
4   Text 4  S 
5   Text 5  G 
6   Text 6  G 
7   Text 7  S 
8   Text 8  G 
9   Text 9  G 
10 Text 10  S 

 

Кто-нибудь может мне помочь?

Спасибо!

Ответ №1:

Если у вас есть только один 1 в строке, как в этом примере, вы можете использовать max.col в базе R —

 cbind(df[1], Class = names(df)[-1][max.col(df[-1])])

#     texts Class
#1   Text 1     E
#2   Text 2     G
#3   Text 3     G
#4   Text 4     S
#5   Text 5     G
#6   Text 6     G
#7   Text 7     S
#8   Text 8     G
#9   Text 9     G
#10 Text 10     S
 

Другой data.table вариант —

 library(data.table)

melt(setDT(df), id.vars = 'texts')[value == 1][
  ,value:= NULL][gtools::mixedorder(texts)]
 

Ответ №2:

Распределите его на длинные, отфильтруйте для них, а затем удалите лишнюю колонку

 df %>%
  pivot_longer(cols = E:G, names_to = 'Class') %>%
  filter(value == 1) %>%
  select(-value)
 

Ответ №3:

С помощью ifelse

 df$E = ifelse(df$E == 1, "E", NA)
df$S = ifelse(df$S == 1, "S", NA)
df$G = ifelse(df$G == 1, "G", NA)

class = do.call(pmax, c(df[-1], na.rm=TRUE))
df = cbind.data.frame(texts = df[,1], class = class)


    texts class
1   Text 1     E
2   Text 2     G
3   Text 3     G
4   Text 4     S
5   Text 5     G
6   Text 6     G
7   Text 7     S
8   Text 8     G
9   Text 9     G
10 Text 10     S
 

Ответ №4:

Мы могли бы использовать c_across после группировки по строкам

 library(dplyr)
df %>%
   rowwise %>% 
   transmute(texts, Class = names(.)[-1][which.max(c_across(E:G))]) %>% 
   ungroup
 

-выход

 # A tibble: 10 x 2
   texts   Class
   <chr>   <chr>
 1 Text 1  E    
 2 Text 2  G    
 3 Text 3  G    
 4 Text 4  S    
 5 Text 5  G    
 6 Text 6  G    
 7 Text 7  S    
 8 Text 8  G    
 9 Text 9  G    
10 Text 10 S    
 

Или с помощью pmap

 library(purrr)
 df %>% 
  transmute(texts, Class = pmap_chr(across(E:G), 
         ~ names(which.max(c(...)))))
     texts Class
1   Text 1     E
2   Text 2     G
3   Text 3     G
4   Text 4     S
5   Text 5     G
6   Text 6     G
7   Text 7     S
8   Text 8     G
9   Text 9     G