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

R中使用case_when批量条件修改变量遇错,求解决方案

问题描述

需要基于自定义函数创建30余个变量,其中N、B、C、Q均为数据框df中的变量列表。附上示例数据、函数代码及报错信息:

示例数据

record_id timeframe                ...
95          2         0                  0
94          2         1                 NA
19          6         0                  1
17          6         1                 NA
18          6         2                 NA
75          9         0                  1
73          9         1                  0
74          9         2                 NA

自定义函数及调用

lag_vars <- function(df, N, B, C, Q){
  df <- df %>% group_by(record_id) %>%
    mutate(N = case_when(
      timeframe == 0 ~ B,
      timeframe > 0 & C == 1 ~ Q,
      timeframe > 0 & C == 0 ~ lag(N)
    ))

  return(df)
}

lag_vars(t, Nt, Bt, Ct, Qt)

错误信息

Error in mutate():
! Problem while computing N = case_when(...).
ℹ The error occurred in group 1: record_id = 2.
Caused by error in case_when():
! timeframe == 0 ~ B, timeframe > 0 & C == 1 ~ Q, timeframe > 0 & C == 0 ~ lag(N) must be length 2 or one, not 3.
Run rlang::last_trace() to see where the error occurred.
Called from: signal_abort(cnd, .file)
Warning messages:
1: Problem while computing N = case_when(...).
ℹ longer object length is not a multiple of shorter object length
ℹ The warning occurred in group 1: record_id = 2.
2: Problem while computing N = case_when(...).
ℹ longer object length is not a multiple of shorter object length
ℹ The warning occurred in group 1: record_id = 2.

疑问:case_when能否使用向量?或者能否将case_when嵌套在其他函数中解决该问题?


解决方案

错误原因分析

  1. 变量列表处理错误:直接将Nt、Bt等变量名向量传入函数,case_when中引用的B、Q是整个变量列表的向量,而分组内的行数(如record_id=2只有2行)与向量长度不匹配,导致报错。
  2. 非标准求值问题:函数中直接使用N、B等符号,无法正确映射到数据框中的变量列表。

修正方案

case_when本身完全支持向量运算,问题出在批量处理多变量的逻辑上。可以通过tidyeval语法结合批量遍历函数来解决:

步骤1:编写单个变量处理函数

先实现处理一组N、B、C、Q变量的逻辑,确保分组内的计算正确:

library(dplyr)
library(purrr)

# 处理单个变量组的函数
lag_single_var <- function(df, N_col, B_col, C_col, Q_col) {
  df %>%
    group_by(record_id) %>%
    arrange(timeframe, .by_group = TRUE) %>% # 确保每个分组内按timeframe排序
    mutate(
      !!N_col := case_when(
        timeframe == 0 ~ .data[[B_col]],
        timeframe > 0 & .data[[C_col]] == 1 ~ .data[[Q_col]],
        timeframe > 0 & .data[[C_col]] == 0 ~ lag(.data[[N_col]])
      )
    ) %>%
    ungroup()
}
  • !!N_col:用tidyeval语法将变量名作为列名赋值
  • .data[[B_col]]:通过字符串引用数据框中的列,避免非标准求值冲突
  • arrange:确保每个分组内的timeframe按顺序排列,保证lag能正确取上一个时间点的值

步骤2:批量处理所有变量组

使用pmap遍历Nt、Bt、Ct、Qt四个变量列表,逐个处理后合并结果:

# 假设Nt、Bt、Ct、Qt是长度相同的变量名字符向量,例如:
# Nt <- c("n_var1", "n_var2", ...)
# Bt <- c("b_var1", "b_var2", ...)

# 批量处理并合并结果
df_processed <- pmap(list(Nt, Bt, Ct, Qt), 
                     ~ lag_single_var(df = t, ..1, ..2, ..3, ..4)) %>%
  reduce(left_join, by = c("record_id", "timeframe"))
  • pmap:按位置匹配四个列表中的元素,逐个传入lag_single_var
  • reduce(left_join):将所有处理后的结果按record_id和timeframe合并,得到最终的数据框

关键说明

  • case_when支持向量:每个条件和结果都可以是向量,只要长度与当前分组(或整个数据框)的行数匹配即可。
  • 批量处理多变量:通过遍历变量列表+tidyeval语法,避免直接传入整个向量导致的长度不匹配问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 19:14:52