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

使用mutate赋值差异变量时dysreg_index超出0-1范围的问题排查

解决血液分析物失调指数计算中重复计数的问题

问题说明

需要基于z评分血液分析物数据集创建四个失调指数:

  • metab_index:包含alt_zscore、alb_zscore、alp_zscore、calcium_zscore、uc_ratio_zscore、sodium_zscore、phos_zscore、pot_zscore、pcv_zscore,以及低值的glob_zscore(低于25%分位数)
  • imm_index:包含baso_per_ul_zscore、esino_per_ul_zscore、lympho_per_ul_zscore、mono_per_ul_zscore、neutro_per_ul_zscore,以及高值的glob_zscore(高于75%分位数)
  • neuro_index:仅包含cortisol_zscore(不在20%-80%分位数区间)
  • dysreg_index:包含所有上述分析物,glob_zscore无论高低值均需计入(即符合任一条件则计1)

指数计算规则:每行中符合失调条件的分析物数量 ÷ 该行非NA分析物总数,结果需在0-1之间。原代码因重复定义glob_zscore的判断函数,导致dysreg_index计算时对glob_zscore重复计数,结果超出合理范围。

修正后的代码

library(dplyr)

# 预计算所有分析物的分位数,避免重复计算且保证一致性
quantiles_df <- df %>%
  summarize(
    across(ends_with("_zscore"), list(
      q20 = ~quantile(., 0.2, na.rm = TRUE),
      q80 = ~quantile(., 0.8, na.rm = TRUE),
      q25 = ~quantile(., 0.25, na.rm = TRUE),
      q75 = ~quantile(., 0.75, na.rm = TRUE)
    ), .names = "{col}_{fn}")
  )

# 定义各分析物的失调判断函数,拆分glob的两个条件
funcs <- list(
  # 代谢类9项分析物
  alt_zscore = function(z) !is.na(z) & !between(z, quantiles_df$alt_zscore_q20, quantiles_df$alt_zscore_q80),
  alb_zscore = function(z) !is.na(z) & !between(z, quantiles_df$alb_zscore_q20, quantiles_df$alb_zscore_q80),
  alp_zscore = function(z) !is.na(z) & !between(z, quantiles_df$alp_zscore_q20, quantiles_df$alp_zscore_q80),
  calcium_zscore = function(z) !is.na(z) & !between(z, quantiles_df$calcium_zscore_q20, quantiles_df$calcium_zscore_q80),
  uc_ratio_zscore = function(z) !is.na(z) & z < quantiles_df$uc_ratio_zscore_q25,
  sodium_zscore = function(z) !is.na(z) & !between(z, quantiles_df$sodium_zscore_q20, quantiles_df$sodium_zscore_q80),
  phos_zscore = function(z) !is.na(z) & !between(z, quantiles_df$phos_zscore_q20, quantiles_df$phos_zscore_q80),
  pot_zscore = function(z) !is.na(z) & !between(z, quantiles_df$pot_zscore_q20, quantiles_df$pot_zscore_q80),
  pcv_zscore = function(z) !is.na(z) & z > quantiles_df$pcv_zscore_q75,
  # glob的两个独立判断条件
  glob_low = function(z) !is.na(z) & z < quantiles_df$glob_zscore_q25,
  glob_high = function(z) !is.na(z) & z > quantiles_df$glob_zscore_q75,
  # 免疫类5项分析物
  baso_per_ul_zscore = function(z) !is.na(z) & z > quantiles_df$baso_per_ul_zscore_q75,
  esino_per_ul_zscore = function(z) !is.na(z) & z > quantiles_df$esino_per_ul_zscore_q75,
  lympho_per_ul_zscore = function(z) !is.na(z) & z > quantiles_df$lympho_per_ul_zscore_q75,
  mono_per_ul_zscore = function(z) !is.na(z) & z > quantiles_df$mono_per_ul_zscore_q75,
  neutro_per_ul_zscore = function(z) !is.na(z) & z > quantiles_df$neutro_per_ul_zscore_q75,
  # 神经内分泌类
  cortisol_zscore = function(z) !is.na(z) & !between(z, quantiles_df$cortisol_zscore_q20, quantiles_df$cortisol_zscore_q80)
)

# 计算各失调指数
df <- df %>%
  mutate(
    # 代谢指数:9项基础分析物 + glob低值判断
    metab_index = {
      base_cols <- names(funcs[1:9])
      numerator <- c(
        mapply(function(fn, x) fn(x), funcs[1:9], pick(all_of(base_cols))),
        funcs$glob_low(pick(glob_zscore))
      )
      denominator <- rowSums(!is.na(pick(all_of(c(base_cols, "glob_zscore")))))
      rowSums(numerator) / denominator
    },
    # 免疫指数:5项基础分析物 + glob高值判断
    imm_index = {
      base_cols <- names(funcs[12:16])
      numerator <- c(
        mapply(function(fn, x) fn(x), funcs[12:16], pick(all_of(base_cols))),
        funcs$glob_high(pick(glob_zscore))
      )
      denominator <- rowSums(!is.na(pick(all_of(c(base_cols, "glob_zscore")))))
      rowSums(numerator) / denominator
    },
    # 神经指数:仅cortisol_zscore
    neuro_index = {
      numerator <- funcs$cortisol_zscore(pick(cortisol_zscore))
      denominator <- as.integer(!is.na(pick(cortisol_zscore)))
      numerator / denominator
    },
    # 总失调指数:所有分析物,glob高低值任一符合即计1
    dysreg_index = {
      all_unique_cols <- names(df)
      # 计算各分析物的失调标记
      dysreg_flags <- c(
        # 代谢9项
        mapply(function(fn, x) fn(x), funcs[1:9], pick(all_of(names(funcs[1:9])))),
        # glob:高低值任一符合则为1
        list(glob_flag = !is.na(pick(glob_zscore)) & (funcs$glob_low(pick(glob_zscore)) | funcs$glob_high(pick(glob_zscore)))),
        # 免疫5项
        mapply(function(fn, x) fn(x), funcs[12:16], pick(all_of(names(funcs[12:16])))),
        # cortisol
        funcs$cortisol_zscore(pick(cortisol_zscore))
      )
      denominator <- rowSums(!is.na(pick(all_of(all_unique_cols))))
      rowSums(dysreg_flags) / denominator
    }
  )

修正核心要点

  1. 拆分glob判断逻辑:将原重复定义的glob_zscore函数拆分为glob_low和glob_high两个独立函数,避免函数覆盖导致的逻辑丢失。
  2. 预计算分位数:提前统一计算所有分析物的分位数,确保各函数使用的分位数一致,同时提升代码运行效率。
  3. 分母去重统计:计算总失调指数时,分母统计所有独特分析物的非NA数量(glob仅算一次),保证分子(符合条件的数量)不会超过分母,结果始终在0-1区间内。
  4. glob总失调逻辑:总失调指数中,glob_zscore只要符合低值或高值任一条件即计为1,避免重复计数问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 08:22:32