如何识别每行具有最大值的N列?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何识别每行具有最大值的N列?相关的知识,希望对你有一定的参考价值。

我的数据看起来像这样:

set.seed(122217)
df <- data.frame(ID = paste0("id",1:100), A = rnorm(100), E = rnorm(100), I = rnorm(100), O = rnorm(100), U = rnorm(100))

我想生成一个包含100行和1 + 3列的新数据框。每行应对应于df中的每个ID,第一列为ID,其他列为First,Second,Third。

我可以用一些非常难看的代码来做到这一点:

library(data.table)
library(dplyr)
# transpose
t_df <- transpose(df[,2:6])
# get row and colnames in order
colnames(t_df) <- df[,1]
rownames(t_df) <- colnames(df[,2:6])
id_largest <-function(data, col){
  values <- data[,col]
  names(values) <- row.names(data)
  values <- sort(values, decreasing = T)
  ranking <- names(values)
  out <- data.frame( id= colnames(data)[col], First=ranking[1], Second=ranking[2], Third=ranking[3])
  return(out)
}

ranking <- purrr::map(1:ncol(t_df), id_largest, data=t_df) %>% rbindlist()

这段代码产生了我想要的东西:

> head(ranking)
id First Second Third
1: id1     A      E     I
2: id2     U      O     I
3: id3     A      E     I
4: id4     E      U     I
5: id5     I      A     U
6: id6     I      A     U

但不是很优雅。这样做有更干净的方法吗?

答案

使用data.table的解决方案:

library(data.table)

melt(setDT(df), id = 1)[order(-value)
                        ][, variable[1:3], ID
                          ][, dcast(.SD, ID ~ rowid(ID, prefix = 'p'))]

这使:

        ID p1 p2 p3
  1: id001  A  E  I
  2: id002  U  O  I
  3: id003  A  E  I
  4: id004  E  U  I
  5: id005  I  A  U
....
 95: id095  O  A  U
 96: id096  U  A  I
 97: id097  A  U  O
 98: id098  U  A  O
 99: id099  I  E  U
100: id100  E  I  U

使用tidyverse实现的逻辑相同:

library(dplyr)
library(tidyr)

df %>% 
  gather(key, value, -1) %>% 
  group_by(ID) %>% 
  arrange(ID, -value) %>% 
  slice(1:3) %>% 
  select(-value) %>% 
  mutate(rn = paste0('p', row_number())) %>% 
  spread(rn, key)

使用数据:

set.seed(122217)
df <- data.frame(ID = sprintf("id%03d",1:100), A = rnorm(100), E = rnorm(100), I = rnorm(100), O = rnorm(100), U = rnorm(100))
另一答案

使用apply的解决方案:

 foo <- colnames(df)[-1]
 data.frame(df[, 1], 
            t(apply(df[, -1], 1, function(x) foo[tail(order(x), 3)]))[, 3:1])

以上是关于如何识别每行具有最大值的N列?的主要内容,如果未能解决你的问题,请参考以下文章

编写程序,求一个二维数组(5行5列)中每行的最大值和每行的和。 帮忙看看哪错了呗,谢谢啦

PowerPivot:如何识别计算列中每组的最大值

洛谷OJ 2216 理想的正方形 单调队列(二维)

cf 1208E

Max Sub-matrix

ndarray每行N个最大值