R语言:如何获取数据框每行最小值与次小值的对应列名?
问题与解决方案
需求说明
我有一个包含100列、1万多行的data frame,已通过以下代码添加了每行的最小值列(lowest)和次小值列(2lowest):
df['2lowest'] <- apply(df, 1, function(x) sort(x, decreasing = FALSE)[2]) df['lowest'] <- apply(df, 1, function(x) sort(x, decreasing = FALSE)[1])
当前数据示例:
x y 2lowest lowest 1 23 3 23 3 2 41 12 41 12 3 32 33 33 32 4 58 38 58 38
需要新增pos(2lowest)和pos(lowest)两列,分别记录2lowest和lowest对应的原始列名,期望结果如下:
x y 2lowest lowest pos(2lowest) pos(lowest) 1 23 3 23 3 x y 2 41 12 41 12 x y 3 32 33 33 32 y x 4 58 38 58 38 x y
实现方法
方法1:一次性计算值与对应列名(高效推荐)
避免重复逐行排序,一次遍历完成所有计算:
# 对每行排序,提取最小值、次小值及其列名 row_results <- t(apply(df, 1, function(row_data) { sorted_indices <- order(row_data) c( lowest = row_data[sorted_indices[1]], `pos(lowest)` = names(row_data)[sorted_indices[1]], `2lowest` = row_data[sorted_indices[2]], `pos(2lowest)` = names(row_data)[sorted_indices[2]] ) })) # 将结果合并到原数据框 df <- cbind(df, as.data.frame(row_results))
如果原数据已经有lowest和2lowest列,可以先删除后再合并,避免重复。
方法2:基于现有值列单独计算列名
如果不想重新生成已有的值列,可以直接逐行匹配:
# 计算最小值对应的列名(替换1:2为你的原始数值列范围) df$`pos(lowest)` <- apply(df[, 1:2], 1, function(row) names(row)[which.min(row)]) # 计算次小值对应的列名(用排序索引确保准确性,兼容重复值场景) df$`pos(2lowest)` <- apply(df[, 1:2], 1, function(row) { sorted_indices <- order(row) names(row)[sorted_indices[2]] })
方法3:用tidyverse语法实现
适合熟悉dplyr的用户:
library(dplyr) df <- df %>% rowwise() %>% mutate( # 选中原始数值列(替换x:y为你的实际列范围) original_cols = list(c_across(x:y)), `pos(lowest)` = names(original_cols)[which.min(original_cols)], `pos(2lowest)` = names(original_cols)[order(original_cols)[2]] ) %>% ungroup() %>% select(-original_cols) # 删除临时辅助列
内容的提问来源于stack exchange,提问作者searchandprint
相关产品推荐
相关产品推荐

