求数据框每行多列的最小/最大值及对应列名的解决方案
解决方案:计算数据框每行指定列的最小/最大值及对应列名
我来帮你搞定这个需求!针对每行计算多列的最小值(或最大值)以及对应的列名,这里有几种高效的实现方式,不用依赖gather那种相对繁琐的分组操作:
方法1:用dplyr(tidyverse风格)
你之前尝试过rowwise但没成功,大概率是没正确搭配c_across来选中目标列,或者没处理列名的提取。试试这个完整的写法:
library(dplyr) library(tibble) # 你的原始数据框 df <- tribble( ~name, ~type_1, ~type_2, ~type_3, "a", 1, 5, 2, "b", 2, 2, 6, "c", 3, 8, 2 ) # 计算最小值和对应列名 result_df <- df %>% rowwise() %>% mutate( # 选中所有type_开头的列,计算每行最小值 min_val = min(c_across(starts_with("type_"))), # 找到最小值所在的列名 min_col = names(select(cur_data(), starts_with("type_")))[which.min(c_across(starts_with("type_")))] ) %>% ungroup() # 取消行分组,恢复常规数据框操作 print(result_df)
如果要计算最大值,只需要把min改成max,which.min改成which.max即可。
方法2:用data.table(适合大数据集,效率更高)
如果你的数据量很大,data.table的方法会比dplyr更快:
library(data.table) setDT(df) # 先定义要处理的目标列 type_cols <- grep("^type_", names(df), value = TRUE) # 添加最小值和对应列名 df[, `:=`( min_val = do.call(pmin, .SD), # 用max.col找最小值位置(取负后找最大值位置等价于找最小值),ties.method处理平局 min_col = type_cols[max.col(-.SD, ties.method = "first")] ), .SDcols = type_cols] print(df)
同样,要计算最大值的话,把pmin改成pmax,-.SD改成.SD就行。
方法3:Base R 实现(简单直接)
如果不想加载额外包,用base R的apply也能快速搞定:
# 你的原始数据框 df <- tribble( ~name, ~type_1, ~type_2, ~type_3, "a", 1, 5, 2, "b", 2, 2, 6, "c", 3, 8, 2 ) # 选中目标列 type_cols <- grep("^type_", names(df), value = TRUE) type_data <- df[type_cols] # 逐行计算最小值和对应列名 min_vals <- apply(type_data, 1, min) min_cols <- apply(type_data, 1, function(x) names(x)[which.min(x)]) # 合并到原数据框 result_df <- cbind(df, min_val = min_vals, min_col = min_cols) print(result_df)
补充说明
你之前尝试的pmax(或pmin)函数本身只能返回每行的最大/最小值,但没法直接获取对应的列名,所以需要搭配which.max/which.min或者max.col这类函数来定位列的位置,再提取列名。
内容的提问来源于stack exchange,提问作者Deniz Topcu
相关产品推荐
相关产品推荐

