首页 > 解决方案 > 对于每一行,按 desc 顺序排序前 5 个值并获得列名

问题描述

我有一个数据框,对于每一行,我想提取每行中具有最大值的前 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 行的预期 O/P 应为 **

a4 a5 a3 a2 a6

或者

a4 a5 a3 a6 a2

我的 O/P 是

在此处输入图像描述

如果可能的话,我会很感激基于 dplyr 的解决方案

标签: rdplyrtidyversetidyr

解决方案


试试这种方法,问题是你有一个额外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  

推荐阅读