如何用R语言获取每行排除GROUP1-3列的最大值对应列名?
问题描述

以下是我当前使用的R代码:
library('tidyverse') library ('dplyr') Brian <- c(92.835, 89.035, 99.222, 93.581) Buckley <- c(75.265, 86.258, 93.972, 96.872) Chris <- c(91.442, 103.999, 91.291, 92.505) Catherine <- c(81.244, 73.040, 78.455, 98.972) David <- c(87.153, 60.062, 62.248, 87.852) Donald <- c(93.395, 91.905, 102.502, 107.63) Greg <- c(79.571, 73.702, 67.326, 89.493) Matt <- c(78.585, 48.074, 81.387, 76.074) Michael <- c(96.933, 78.709, 82.623, 66.325) df <- data.frame(Brian, Buckley, Chris, Catherine, David, Donald, Greg, Matt, Michael) group1 <- data.frame(Brian, Matt, Michael) group2 <- data.frame(Buckley, Chris, Catherine) group3 <- data.frame(David, Donald, Greg) group1a <- group1 %>% mutate(Group1 = names(.)[max.col(.)]) group2a <- group2 %>% mutate(Group2 = names(.)[max.col(.)]) group3a <- group3 %>% mutate(Group3 = names(.)[max.col(.)]) GROUP1 <- dplyr::pull(group1a, 'Group1') GROUP2 <- dplyr::pull(group2a, 'Group2') GROUP3 <- dplyr::pull(group3a, 'Group3') ALL <- cbind(df, GROUP1, GROUP2, GROUP3)
上述代码展示了一个更长表格的4行数据。我希望为该表格新增一列GROUP4,该列的值为每行中排除GROUP1、GROUP2、GROUP3列对应的列名后,数值最大的列的名称,示例中四行的结果应为Brian、Buckley、Chris、Buckley。作为R新手,我尝试查找dplyr相关方法但未能解决,寻求可行的实现代码。
解决方案
可以用dplyr的行分组功能逐行处理,核心逻辑是每行先确定要排除的列名,再在剩余列中找到最大值对应的列名:
library(dplyr) # 在现有ALL数据框基础上新增GROUP4列 ALL <- ALL %>% rowwise() %>% mutate( # 收集当前行需要排除的三个分组列名 exclude = c(GROUP1, GROUP2, GROUP3), # 从原始df中筛选剩余列,找到当前行最大值对应的列名 GROUP4 = names(df)[which.max(select(df, -all_of(exclude))[cur_row(), ])] ) %>% ungroup() %>% select(-exclude) # 删除临时使用的exclude列
代码说明:
rowwise():让后续操作按行独立执行exclude = c(GROUP1, GROUP2, GROUP3):把当前行的三个分组列名打包成向量,作为排除目标select(df, -all_of(exclude)):从原始数据框中剔除指定列,保留剩余数值列which.max(...):定位剩余列中当前行数值最大的位置,再通过names(df)获取对应列名ungroup():取消行分组,恢复数据框默认的列操作模式select(-exclude):清理临时创建的exclude列,保持数据整洁
运行后ALL数据框会新增符合要求的GROUP4列,四行结果正好是Brian、Buckley、Chris、Buckley。
如果习惯函数式编程,也可以用purrr包的pmap函数实现:
library(purrr) ALL$GROUP4 <- pmap_chr(ALL, function(...) { row_data <- tibble(...) exclude_cols <- c(row_data$GROUP1, row_data$GROUP2, row_data$GROUP3) names(df)[which.max(df[cur_row(), !names(df) %in% exclude_cols])] })
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

