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

使用mutate(across(all_of()))结合cur_column()出现递归错误

问题解决:在dplyr的across中动态引用对应后缀列

核心问题分析

你遇到的递归错误和列引用偏差,本质是在across()的lambda表达式中,使用!!sym()进行tidyeval的时机不匹配,结合嵌套数据框的环境特性,导致无法正确解析动态生成的列名。硬编码列名能运行但复用性差,而cur_column()需要配合正确的列索引方式来获取对应的_OVERRIDE列。

修正后的代码

方法1:使用.data代词动态索引(推荐)

.data是dplyr中的特殊代词,能安全访问当前数据框的列,结合cur_column()可以动态拼接列名:

library(dplyr)

# 定义趋势函数
TREND_LOSS <- function(LOSSES, YEARS, OVERRIDES) {
  x <- YEARS
  y <- log(LOSSES)
  xy <- x * y
  x_sq <- x * x
  sum_x <- sum(x)
  sum_y <- sum(y)
  sum_xy <- sum(xy)
  sum_x_sq <- sum(x_sq)
  n <- length(YEARS)
  Slope <- (n*sum_xy - sum_x*sum_y) / (n*sum_x_sq - sum_x*sum_x)
  
  OVERRIDES[is.na(OVERRIDES)] <- Slope
  TRENDED_LOSSES <- LOSSES * exp(OVERRIDES)
  return(TRENDED_LOSSES)
}

# 构造数据
LR_DATA <- data.frame(STATE = c(1,2,3),
                      YEAR = c(2000,2001,2002),
                      DEVT_A = c(2,4,6),
                      DEVT_B = c(3,6,9),
                      DEVT_C = c(4,8,12))

LOSS_COLS <- c("DEVT_A", "DEVT_B", "DEVT_C")

DATA_OVERRIDE <- data.frame(STATE = c(1,2,3),
                            DEVT_A_OVERRIDE = c(NaN,1,1),
                            DEVT_B_OVERRIDE = c(1,1,1),
                            DEVT_C_OVERRIDE = c(1.5,1.5,1.5))

LR_DATA <- LR_DATA %>% left_join(DATA_OVERRIDE, by = 'STATE')

# 修正后的处理流程
TRENDED_LR_DATA <- LR_DATA %>% 
  summarise(across(everything(), list), .groups = "keep") %>%
  mutate(across(all_of(LOSS_COLS), 
                ~list(TREND_LOSS(unlist(.x), 
                                 unlist(YEAR), 
                                 unlist(.data[[paste0(cur_column(), "_OVERRIDE")]])))))

方法2:使用cur_column()结合get()函数

如果习惯用基础R的索引方式,也可以用get()在当前环境中获取列:

TRENDED_LR_DATA <- LR_DATA %>% 
  summarise(across(everything(), list), .groups = "keep") %>%
  mutate(across(all_of(LOSS_COLS), 
                ~list(TREND_LOSS(unlist(.x), 
                                 unlist(YEAR), 
                                 unlist(get(paste0(cur_column(), "_OVERRIDE"), envir = cur_data()))))))

关键修正点说明

  1. 替换!!sym()为.data[[...]]:在across()的lambda中,.data能直接指向当前数据框,动态拼接的列名通过[[ ]]索引,避免了tidyeval的时机冲突,解决递归错误。
  2. cur_column()的正确使用:cur_column()在across()内部会返回当前正在处理的列名,配合paste0()生成对应的_OVERRIDE列名,确保每个损失列都匹配到专属的覆盖列。
  3. 嵌套数据的unlist()处理:因为summarise(across(everything(), list))把所有列转成了嵌套列表,所以必须用unlist()把向量从列表中提取出来,才能传入TREND_LOSS函数计算。

验证结果

运行修正后的代码,每个DEVT_*列都会使用对应的DEVT_*_OVERRIDE列数据:

  • DEVT_A会用DEVT_A_OVERRIDE(NaN被替换为计算的Slope)
  • DEVT_B用DEVT_B_OVERRIDE
  • DEVT_C用DEVT_C_OVERRIDE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 08:54:16