You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R的dplyr中获取指定列的行最小值及对应列名后缀

问题与解决方案

数据集

library(dplyr)
Data <- tibble(Code = letters[1:6],
            Min_0 = c(12.3, NA, 1.1, NA, 0, NA),
            Min_1 = c(3.6, NA, 12.4, 1.7, 15.6, NA),
            Min_2 = c(45.6, NA, 2.4, 28.9, 32.7, NA),
            Min_3 = c(2.3, NA, NA, NA, NA, NA),
            Min_4 = c(52.4, NA, 23.6, 4.6, 0, NA),
            Min_5 = c(0, NA, 5.7, NA, 0.1, NA))

需求

需要为每行添加两列:

  • Min_Time:取Min_1至Min_5列中的最小值,若这些列全为NA则设为NA;
  • Min_ID:取对应最小值所在列名的最后一位数字,示例输出如下:
Data %>% mutate(Min_ID = c(5, NA, 2, 1, 4, NA))

已实现部分(Min_Time)

已通过自定义函数实现Min_Time的计算,代码如下:

Min_Function <- function(x, f, ...) ifelse(all(is.na(x)), NA, 
                                   ifelse(all(is.na(x)), 
                                          0, f(x[x >= 0], na.rm = TRUE, ...)))

Data %>%
    rowwise() %>%
    mutate(Min_Time = Min_Function(c_across(starts_with("Min_") & -ends_with("0")), min))

Min_ID的实现方案

可以在现有rowwise()流程中,结合列名提取和位置匹配来生成Min_ID,同时保持动态筛选列的逻辑:

# 需提前加载stringr包用于提取数字,若不想加载可看下方替代方案
library(stringr)

Data %>%
    rowwise() %>%
    mutate(
        # 临时存储每行的目标列数据与列名,避免重复筛选
        target_data = list(c_across(starts_with("Min_") & -ends_with("0"))),
        Min_Time = Min_Function(unlist(target_data), min),
        Min_ID = ifelse(all(is.na(unlist(target_data))), 
                        NA, 
                        # 提取最小值对应列名的末尾数字
                        str_extract(names(unlist(target_data))[which.min(unlist(target_data))], "\\d+$") %>% as.integer())
    ) %>%
    select(-target_data)  # 移除临时辅助列

无stringr包的替代写法

如果不想依赖stringr,可以用基础R的sub函数提取列名数字:

Data %>%
    rowwise() %>%
    mutate(
        target_data = list(c_across(starts_with("Min_") & -ends_with("0"))),
        Min_Time = Min_Function(unlist(target_data), min),
        Min_ID = ifelse(all(is.na(unlist(target_data))), 
                        NA, 
                        sub("Min_", "", names(unlist(target_data))[which.min(unlist(target_data))]) %>% as.integer())
    ) %>%
    select(-target_data)

逻辑说明

  1. 用list()存储每行的目标列数据,避免重复调用c_across提升效率;
  2. which.min()定位最小值所在的位置,结合names()获取对应列名;
  3. 通过字符串处理提取列名末尾的数字,转为整数类型;
  4. 用ifelse处理全NA的行,返回NA值匹配需求。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 16:23:23