R语言如何为数据框每行数值变量生成降序排名?
R语言实现行内数值变量的排名(1对应最大值)
当然有合适的方法可以实现需求,下面是几种常用的解决方案,结合你的示例数据展开:
先创建示例数据框
首先把你提供的测试数据转换成可直接运行的R代码:
df <- data.frame( Diabetes = c(0.040457, 0.279323, 0.328068, 0.107959, 0.131555, 0.999961, 0.129270, 0.441010), Lyme = c(0.326594, 0.877446, 0.837669, 0.678297, 0.418380, 0.619517, 0.024533, 0.741781), Anaemia = c(0.14, 0.37, 0.48, 0.12, 0.123, 0.4, 0.8, 0.9), row.names = c("Anthony", "Mary", "Paul", "Markus", "Jeremy", "Sarah", "Eve", "Whitney") )
方法1:Base R 原生实现
用apply逐行处理,配合rank函数,通过取反数值让最大值对应排名1:
# 逐行计算排名,ties.method设置相同值的排名规则(可选min/first等) rank_matrix <- apply(df, 1, function(x) rank(-x, ties.method = "min")) # 转置并转为数据框,修改列名 rank_df <- as.data.frame(t(rank_matrix)) colnames(rank_df) <- paste0(colnames(df), "_Rank") # 合并原数据和排名数据 result_df <- cbind(df, rank_df)
说明:rank(-x)是核心操作——默认rank是从小到大排序,取反后原最大值变为最小的负数,排名自然为1;ties.method可根据需求调整:比如"min"给相同值分配最小的共同排名,"first"则按数值出现顺序排名。
方法2:tidyverse 风格实现(dplyr + tidyr)
适合习惯tidyverse语法的用户,通过长格式转换统一计算排名:
library(dplyr) library(tidyr) result_df <- df %>% rownames_to_column("Name") %>% # 行名转为普通列 pivot_longer(-Name, names_to = "Disease", values_to = "Probability") %>% # 转长格式 group_by(Name) %>% # 按每个人分组 mutate(Rank = rank(-Probability, ties.method = "min")) %>% # 计算组内排名 pivot_wider( names_from = Disease, values_from = c(Probability, Rank) # 转回宽格式,保留概率和排名 ) %>% rename_with(~gsub("Probability_", "", .), starts_with("Probability_")) %>% # 还原原列名 relocate(all_of(colnames(df)), .before = 1) %>% # 调整列顺序,原数据在前 column_to_rownames("Name") # 恢复行名
方法3:data.table 高效实现(适合大数据)
如果数据量较大,data.table的逐组计算效率更高:
library(data.table) dt <- as.data.table(df, keep.rownames = "Name") result_dt <- dt[, c(.SD, lapply(.SD, function(x) rank(-x, ties.method = "min"))), by = Name, .SDcols = colnames(df) ] # 修改自动生成的排名列名 setnames(result_dt, paste0(colnames(df), "_Rank"), grep("^V", colnames(result_dt), value = TRUE)) # 转为数据框并恢复行名(可选) result_df <- as.data.frame(result_dt) rownames(result_df) <- result_df$Name result_df$Name <- NULL
查看结果
运行任意一种方法后,执行print(result_df, digits = 3)就能得到你想要的格式,比如:
Diabetes Lyme Anaemia Diabetes_Rank Lyme_Rank Anaemia_Rank Anthony 0.0405 0.3266 0.140 3 1 2 Mary 0.2793 0.8774 0.370 3 1 2 Paul 0.3281 0.8377 0.480 2 1 3 Markus 0.1080 0.6783 0.120 3 1 2 Jeremy 0.1316 0.4184 0.123 2 1 3 Sarah 1.0000 0.6195 0.400 1 2 3 Eve 0.1293 0.0245 0.800 2 3 1 Whitney 0.4410 0.7418 0.900 3 2 1
内容的提问来源于stack exchange,提问作者ADayWithoutRain
相关产品推荐
相关产品推荐

