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

R语言dplyr管道按行计算max时返回NA而非-Inf的方法

问题复现

以下代码可完整复现全NA行返回-Inf的异常:

library(dplyr)

# 构造测试用日期数据框
df <- tibble(
  id = 1:3,
  mr_daterd_1 = as.Date(c("2023-01-05", "2023-02-10", NA)),
  mr_daterd_2 = as.Date(c("2023-03-12", NA, NA)),
  date_contact_1 = as.Date(c("2023-01-02", "2023-02-15", NA)),
  date_contact_2 = as.Date(c("2022-12-20", NA, NA))
)

# 原有管道写法,全NA行返回-Inf
df_problem <- df %>%
  rowwise() %>%
  mutate(
    latest_mri = max(c_across(starts_with("mr_daterd")), na.rm = TRUE),
    latest_contact = max(c_across(starts_with("date_contact")), na.rm = TRUE)
  ) %>%
  ungroup()

运行上述代码后,第3行所有MRI、接触日期列均为NA,计算得到的latest_mri、latest_contact值为-Inf,不符合日期类型预期。

解决方案

完全保留原有rowwise + c_across + starts_with的管道逻辑,不需要调整选列或行计算框架,两种写法可直接嵌入现有代码:

写法1:直接在mutate中加判断

不需要额外定义函数,仅对全NA场景做分支判断即可:

df_fixed <- df %>%
  rowwise() %>%
  mutate(
    latest_mri = if (all(is.na(c_across(starts_with("mr_daterd"))))) {
      NA_Date_
    } else {
      max(c_across(starts_with("mr_daterd")), na.rm = TRUE)
    },
    latest_contact = if (all(is.na(c_across(starts_with("date_contact"))))) {
      NA_Date_
    } else {
      max(c_across(starts_with("date_contact")), na.rm = TRUE)
    }
  ) %>%
  ungroup()

写法2:封装安全取最大值函数(多分组场景更简洁)

如果同类型前缀分组较多,可以先封装一个适配日期类型的安全max函数,直接替换原有max调用即可,代码更整洁:

# 定义日期类型安全取最大值函数
safe_date_max <- function(x) {
  if (all(is.na(x))) return(NA_Date_)
  max(x, na.rm = TRUE)
}

# 嵌入原有管道
df_fixed2 <- df %>%
  rowwise() %>%
  mutate(
    latest_mri = safe_date_max(c_across(starts_with("mr_daterd"))),
    latest_contact = safe_date_max(c_across(starts_with("date_contact")))
  ) %>%
  ungroup()
  • 两种写法输出结果一致:非全NA行正常返回分组内最晚日期,全NA行返回日期类型的NA,不会出现-Inf值,也不会改变原有数据框的列类型
  • 不要用通用NA替换NA_Date_:通用NA为逻辑类型,直接赋值给日期列会触发类型不匹配错误
  • 不需要改动原有选列逻辑:starts_with匹配前缀、c_across抓取值、rowwise按行计算的逻辑完全保留,和原有代码完全兼容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 04:39:36