首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何通过dplyr获得选定的max/min值(即第二大/最小)的列名?

如何通过dplyr获得选定的max/min值(即第二大/最小)的列名?
EN

Stack Overflow用户
提问于 2022-10-20 06:38:54
回答 3查看 61关注 0票数 1

作为标题,如何通过dplyr获得跨行的第二/第三大/最小值的列名?(注意:比较从gp1到gp3的值,我修改了原始数据)

一种方法是在基数R中使用apply

代码语言:javascript
运行
复制
a <- data.frame(name=letters[1:9], gp1=c(3:11), gp2=c(1:9), gp3=c(8,8,2,6,6,6,12,12,6))
##
##   name gp1 gp2 gp3
## 1    a   3   1   8
## 2    b   4   2   8
## 3    c   5   3   2
## 4    d   6   4   6
## 5    e   7   5   6
## 6    f   8   6   6
## 7    g   9   7  12
## 8    h  10   8  12
## 9    i  11   9   6

a$max1_colname <- apply(a, 1, function(t) colnames(a)[which.max(t)])
## There will be some warnings. the problem of name column? 
##
##   name gp1 gp2 gp3 max1_colname
## 1    a   3   1   8          gp3
## 2    b   4   2   8          gp3
## 3    c   5   3   2          gp1
## 4    d   6   4   6          gp1
## 5    e   7   5   6          gp1
## 6    f   8   6   6          gp1
## 7    g   9   7  12          gp3
## 8    h  10   8  12          gp3
## 9    i  11   9   6          gp1

如何通过使用dplyr (忽略第4行有两个最大值)来完成它,第二大列名如何?

Extern外:更复杂的是,如果有两个最大值(例如第4行),如何得到如下结果:

代码语言:javascript
运行
复制
##
##   name gp1 gp2 gp3 max1_colname
## 1    a   3   1   8          gp3
## 2    b   4   2   8          gp3
## 3    c   5   3   2          gp1
## 4    d   6   4   6          gp1+gp3
## 5    e   7   5   6          gp1
## 6    f   8   6   6          gp1
## 7    g   9   7  12          gp3
## 8    h  10   8  12          gp3
## 9    i  11   9   6          gp1

谢谢。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-10-20 07:27:04

您可以在一个max.col调用中使用mutate。请注意,这将只保留一个值,并且可以使用ties.method处理领带。默认情况下,它随机选择一个平分最大值。

代码语言:javascript
运行
复制
library(dplyr)
a %>%
  mutate(max1_colname = names(select(., gp1:gp3))[max.col(select(., gp1:gp3))])

对于第二个更复杂的案例,您可以这样做:

代码语言:javascript
运行
复制
a %>%
  rowwise() %>% 
  mutate(max1_colname = paste(names(select(., -name))[c_across(-name) == max(c_across(-name))], collapse = "+"))

#   name    gp1   gp2   gp3 max1_colname
# 1 a         3     1     8 gp3         
# 2 b         4     2     8 gp3         
# 3 c         5     3     2 gp1         
# 4 d         6     4     6 gp1+gp3     
# 5 e         7     5     6 gp1         
# 6 f         8     6     6 gp1         
# 7 g         9     7    12 gp3         
# 8 h        10     8    12 gp3         
# 9 i        11     9     6 gp1         

若要获得第二个(或更多)最大值,请使用orderdecreasing = TRUE

代码语言:javascript
运行
复制
a %>%
  rowwise() %>% 
  mutate(max2_colname = names(.)[order(c_across(everything()), decreasing = TRUE)[2]])

#     gp1   gp2   gp3 max2_colname
# 1     3     1     8 gp1         
# 2     4     2     8 gp1         
# 3     5     3     2 gp2         
# 4     6     4     6 gp3         
# 5     7     5     6 gp3         
# 6     8     6     6 gp2         
# 7     9     7    12 gp1         
# 8    10     8    12 gp1         
# 9    11     9     6 gp2         

对于更复杂的情况,您希望获得最大的n,并获得它们的全部,您可以使用dense_rank + which

代码语言:javascript
运行
复制
a %>%
  rowwise() %>% 
  mutate(max1_colname = paste(names(.)[which(dense_rank(-c_across(everything())) == 2)], collapse = "+"))

#     gp1   gp2   gp3 max1_colname
# 1     3     1     8 gp1         
# 2     4     2     8 gp1         
# 3     5     3     2 gp2         
# 4     6     4     6 gp2         
# 5     7     5     6 gp3         
# 6     8     6     6 gp2+gp3     
# 7     9     7    12 gp1         
# 8    10     8    12 gp1         
# 9    11     9     6 gp2         
票数 3
EN

Stack Overflow用户

发布于 2022-10-20 07:07:09

第一部分可通过以下方式完成:

代码语言:javascript
运行
复制
library(tidyverse)

a %>% 
  rowwise() %>% 
  mutate(max1_colname = names(.)[which.max(c_across(everything()))])

gp1 gp2 gp3 max1_colname
3   1   8   gp3
4   2   8   gp3
5   3   2   gp1
6   4   6   gp1
7   5   6   gp1
8   6   6   gp1
9   7   12  gp3
10  8   12  gp3
11  9   6   gp1

第二部分的解决办法:

代码语言:javascript
运行
复制
a1 <- a %>% mutate(id = row_number()) %>% 
  pivot_longer(-id)

a2 <- a1 %>% 
  group_by(id) %>% 
  top_n(value, n = 1) %>% 
  mutate(max1_colname = paste0(name, collapse = "+")) %>% 
  select(id, max1_colname) %>% 
  distinct()
  
a1 %>% 
  left_join(a2, by = c("id")) %>% 
  pivot_wider() %>% 
  relocate(max1_colname, .after = gp3) %>% 
  select(-id) 

gp1 gp2 gp3 max1_colname
3   1   8   gp3
4   2   8   gp3
5   3   2   gp1
6   4   6   gp1+gp3
7   5   6   gp1
8   6   6   gp1
9   7   12  gp3
10  8   12  gp3
11  9   6   gp1
票数 2
EN

Stack Overflow用户

发布于 2022-10-20 07:59:52

还请注意,有一个基本的max.col函数,唯一的问题是它返回一个索引(可以设置为第一个,最后,随机)。

代码语言:javascript
运行
复制
a %>%
  mutate(max1_colname = paste("grp", max.col(.), sep = ""))

#   gp1 gp2 gp3 max1_colname
# 1   3   1   8         grp3
# 2   4   2   8         grp3
# 3   5   3   2         grp1
# 4   6   4   6         grp1
# 5   7   5   6         grp1
# 6   8   6   6         grp1
# 7   9   7  12         grp3
# 8  10   8  12         grp3
# 9  11   9   6         grp1
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74135397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档