R语言计算vasopressor_duration时新列全NA问题求助(附可复现代码)
问题:计算升压药时长时新列全为NA的解决方法
问题背景
需要生成vasopressor_on(指定列的最小值)、vasopressor_off(指定列的最大值),并计算两者的时长vasopressor_duration,要求NA行保留NA或转为0。简化数据集测试正常,但在真实数据集(test_df)中,添加时长计算代码后,所有新生成列都变成NA;移除时长计算代码后,vasopressor_on和vasopressor_off能正常生成值。
可复现代码如下:
study_ID <- c(5,6,7) randomisation <- (c("2021-01-01 11:00", NA, "2021-01-03 10:00")) water_on <- (c("2021-01-01 13:00", NA,"2021-01-04 09:45")) water_off <- (c("2021-01-01 18:00", NA,"2021-01-04 11:00")) trial_A <- data.frame(study_ID, randomisation, water_on, water_off) trial_A_1 <- trial_A %>% dplyr::mutate(across(c(randomisation, water_on, water_off), ymd_hm)) robustmax <- function(x) {if (length(x)>0) max(x) else -Inf} robustmin <- function(x) {if (length(x)>0) min(x) else Inf} Primary <- trial_A_1 %>% rowwise() %>% dplyr::mutate(vasopressor_on = robustmin(c_across(c(randomisation, water_on, water_off)))) %>% dplyr::mutate(vasopressor_off = robustmax(c_across(c(randomisation, water_on, water_off)))) %>% dplyr::mutate(vasopressor_duration = (vasopressor_on %--% vasopressor_off) %>% as.duration() / dhours()) %>% ungroup() # 真实数据集代码(修正原拼写错误:test_ df → test_df) test_df <- data.frame( true_adrenaline_on = as.POSIXct( rep(c("2020-08-31 13:05:00", NA, "2020-09-17 20:58:00", NA), c(1L, 3L, 1L, 5L)), tz = "UTC" ), true_noradrenaline_on = as.POSIXct( c( "2020-08-31 13:05:00", "2020-09-03 14:00:00", NA, "2020-09-17 16:00:00", "2020-09-17 23:00:00", NA, "2020-09-21 14:10:00", "2020-09-24 14:17:00", NA, "2020-09-28 14:20:00" ), tz = "UTC" ), true_vasopressin_on = as.POSIXct( rep(c(NA, "2020-09-18 09:00:00", NA, "2020-09-28 19:00:00"), rep(c(4L, 1L), 2)), tz = "UTC" ), true_phenylephrine_on = as.POSIXct(rep(NA_character_, 10L), tz = "UTC"), true_metaraminol_on = as.POSIXct(rep(NA_character_, 10L), tz = "UTC"), true_adrenaline_off = as.POSIXct( rep(c("2020-09-01 08:00:00", NA, "2020-09-18 09:00:00", NA), c(1L, 3L, 1L, 5L)), tz = "UTC" ), true_noradrenaline_off = as.POSIXct( c( "2020-09-01 06:00:00", "2020-09-04 22:00:00", NA, "2020-09-17 18:00:00", "2020-09-21 07:00:00", NA, "2020-09-21 22:00:00", "2020-09-25 00:00:00", NA, "2020-09-29 16:00:00" ), tz = "UTC" ), true_vasopressin_off = as.POSIXct( rep(c(NA, "2020-09-21 07:00:00", NA, "2020-09-29 04:00:00"), rep(c(4L, 1L), 2)), tz = "UTC" ), true_phenylephrine_off = as.POSIXct(rep(NA_character_, 10L), tz = "UTC"), true_metaraminol_off = as.POSIXct(rep(NA_character_, 10L), tz = "UTC") ) # 原真实数据集处理代码 Primary <- test_df %>% rowwise() %>% dplyr::mutate(vasopressor_on = robustmin(c_across(c(true_adrenaline_on, true_noradrenaline_on, true_vasopressin_on,true_phenylephrine_on,true_metaraminol_on)))) %>% dplyr::mutate(vasopressor_off = robustmax(c_across(c(true_adrenaline_off, true_noradrenaline_off, true_vasopressin_off,true_phenylephrine_off,true_metaraminol_off)))) %>% dplyr::mutate(vasopressor_duration = (vasopressor_on %--% vasopressor_off) %>% as.duration() / dhours()) %>% ungroup()
问题原因
robustmin/robustmax函数逻辑错误:当某一行所有值都是NA时,c_across返回的向量长度仍大于0,函数会执行min(x)/max(x),结果为NA;全NA行生成的NA值会导致后续时长计算出错,进而引发所有新列异常。- 时长计算未处理异常情况:当
vasopressor_on晚于vasopressor_off时,计算出的时长为负数,且未处理NA值的情况,导致结果不符合预期。
解决方案
1. 修正鲁棒性函数
过滤NA值后再判断是否有有效值,不存在有效值时返回NA,避免后续时间区间计算出错:
robustmax <- function(x) { x_non_na <- na.omit(x) if (length(x_non_na) > 0) max(x_non_na) else NA } robustmin <- function(x) { x_non_na <- na.omit(x) if (length(x_non_na) > 0) min(x_non_na) else NA }
2. 修正时长计算逻辑
判断vasopressor_on和vasopressor_off的有效性与时间顺序,符合要求则计算时长,否则返回NA或0:
library(dplyr) library(lubridate) # 处理真实数据集 Primary <- test_df %>% rowwise() %>% mutate(vasopressor_on = robustmin(c_across(c(true_adrenaline_on, true_noradrenaline_on, true_vasopressin_on, true_phenylephrine_on, true_metaraminol_on)))) %>% mutate(vasopressor_off = robustmax(c_across(c(true_adrenaline_off, true_noradrenaline_off, true_vasopressin_off, true_phenylephrine_off, true_metaraminol_off)))) %>% mutate(vasopressor_duration = case_when( is.na(vasopressor_on) | is.na(vasopressor_off) ~ NA_real_, vasopressor_on > vasopressor_off ~ 0, # 若开始晚于结束,返回0,可按需调整 TRUE ~ as.duration(vasopressor_on %--% vasopressor_off) / dhours() )) %>% ungroup()
验证结果
运行修正后的代码后:
- 非NA行能正常生成
vasopressor_on、vasopressor_off和对应的时长 - 全NA行的
vasopressor_on、vasopressor_off和vasopressor_duration均为NA,符合需求 - 若出现
vasopressor_on晚于vasopressor_off的情况,时长返回0(可根据实际需求调整该逻辑)
内容的提问来源于stack exchange,提问作者GJW
相关产品推荐
相关产品推荐

