Для каждой строки отсортируйте 5 лучших значений в порядке убывания и получите там имя столбца

#r #dplyr #tidyverse #tidyr

#r #dplyr #tidyverse #tidyr

Вопрос:

У меня есть фрейм данных, и для каждой строки я хочу извлечь верхние 5 столбцов с максимальным значением в каждой строке

 DF <- data.frame(a1=c(10,45,100,5000,23,45,2,23,56),
                 a2=c(60,20,5,2,1,2,3,4,5),
                 a3=c(90,2,0,0,0,4,-5,-3,-2),
                 a4=c(900,122,30,40,50,64,-75,-83,-92),
                 a5=c(190,32,30,50,80,49,-50,-7,-2),
                 a6=c(30,27,80,54,84,49,-50,-37,-23),
                 a7=c(0,32,39,50,80,9,-5,-7,-23))

  

Я попытался использовать приведенный ниже подход

 k <- 5

mx <- t(apply(DF,1,function(x)names(DF)[sort(head(order(x,decreasing=TRUE),k))]))
mx<-as.data.frame(mx)

  

Я могу получить результаты, но порядок неправильный для всех строк

например

Ввод

введите описание изображения здесь

** Ожидаемый вывод / вывод для строки 1 должен быть **

a4 a5 a3 a2 a6

или

a4 a5 a3 a6 a2

Мой O / P

введите описание изображения здесь

Я был бы признателен за решение на основе dplyr, если это возможно

Ответ №1:

Попробуйте этот подход, проблема заключалась в том, что у вас был дополнительный sort() , который снова переупорядочивал значения:

 #Code
mx <- t(apply(DF,1,function(x)names(DF)[head(order(x,decreasing=TRUE),k)]))
mx<-as.data.frame(mx)
  

Вывод:

   V1 V2 V3 V4 V5
1 a4 a5 a3 a2 a6
2 a4 a1 a5 a7 a6
3 a1 a6 a7 a4 a5
4 a1 a6 a5 a7 a4
5 a6 a5 a7 a4 a1
6 a4 a5 a6 a1 a7
7 a2 a1 a3 a7 a5
8 a1 a2 a3 a5 a7
9 a1 a2 a3 a5 a6
  

tidyverse Подход подразумевает изменение данных следующим образом:

 library(tidyverse)
#Code
DF %>%
  #Create an id by row
  mutate(id=1:n()) %>%
  #Reshape
  pivot_longer(cols = -id) %>%
  #Arrange
  arrange(id,-value) %>%
  #Filter top 5
  group_by(id) %>%
  mutate(Var=1:n()) %>%
  filter(Var<=5) %>%
  select(-c(value,Var)) %>%
  #Format
  mutate(Var=paste0('V',1:n())) %>%
  pivot_wider(names_from = Var,values_from=name) %>%
  ungroup() %>%
  select(-id)
  

Вывод:

 # A tibble: 9 x 5
  V1    V2    V3    V4    V5   
  <chr> <chr> <chr> <chr> <chr>
1 a4    a5    a3    a2    a6   
2 a4    a1    a5    a7    a6   
3 a1    a6    a7    a4    a5   
4 a1    a6    a5    a7    a4   
5 a6    a5    a7    a4    a1   
6 a4    a5    a6    a1    a7   
7 a2    a1    a3    a7    a5   
8 a1    a2    a3    a5    a7   
9 a1    a2    a3    a5    a6  
  

Комментарии:

1. спасибо, не могли бы вы написать то же самое и в dplyr

2. @Dexter Конечно, я могу дать вам tidyverse подход. Минутку!

3. @Dexter Я добавил tidyverse подход!

4. Спасибо, дак, я хочу улучшить свое кодирование в R, можете ли вы подсказать мне, как быть лучше

5. @Dexter Будет лучше, если вы будете использовать tidyverse функции, изменяющие форму данных, поскольку вы видели, что apply() вас смутило даже наличие решения вашей проблемы. Попробуйте преобразовать данные, и у вас получится лучше 🙂