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

使用dplyr的case_when替换多列中1为对应行id并将0转为NA

问题解决:dplyr中使用across+case_when替换值报错处理

问题背景

原始数据:

have <- structure(list(a1 = c(1, 1, 0, 1, 1, 1, 1, 1, 1, 1), a2 = c(1, 
1, 0, 1, 1, 0, 1, 1, 1, 1), b1 = c(0, 0, 0, 0, 0, 1, 0, 0, 0, 
0), b2 = c(1, 1, 0, 0, 0, 1, 0, 0, 0, 0), c1 = c(0, 0, 0, 0, 
1, 0, 0, 0, 0, 0), c2 = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), id = 1:10), 
row.names = c(NA, -10L), class = c("tbl_df", "tbl", "data.frame"))

需求:将a1:c2变量中值为1的替换为对应行的id值,值为0的替换为NA_real_,要求使用dplyr和case_when实现。

尝试代码:

library(dplyr)

want <- have %>%
   mutate(across(c(a1:c2), 
         .fns = ~ case_when(. == 1 ~ id,
                            T ~ NA_real_))
   )

报错信息:

Error in `mutate()`:
! Problem while computing `..1 = across(c(a1:c2), .fns = ~case_when(. == 1 ~ id,
  T ~ NA_real_))`.
Caused by error in `across()`:
! Problem while computing column `a1`.
Caused by error in `` names(message) <- `*vtmp*` ``:
! 'names' attribute [1] must be the same length as the vector [0]
Backtrace:
  1. have %>% ...
  8. dplyr::case_when(a1 == 1 ~ id, T ~ NA_real_)
  9. dplyr:::replace_with(...)
 10. dplyr:::check_type(val, x, name, error_call = error_call)
 11. rlang::abort(msg, call = error_call)
     ...
 16. rlang::cnd_message(c)
 17. rlang:::cnd_message_format(cnd, ...)
 18. rlang (local) cli_format(glue_escape(lines))
 19. rlang:::.rlang_cli_format(x, cli::format_error)
 20. cli::cli_format(x, .envir = emptyenv())

错误原因

报错核心是类型不匹配:id是整数类型,而NA_real_是双精度数值类型,case_when要求所有分支的输出类型必须一致,类型冲突导致无法正常执行。

解决方案

将id转换为双精度数值类型,确保和NA_real_类型一致,修正后的代码如下:

library(dplyr)

want <- have %>%
  mutate(across(a1:c2, 
                ~ case_when(. == 1 ~ as.numeric(id),
                            TRUE ~ NA_real_))
  )

如果不需要严格使用case_when,也可以用更简洁的ifelse实现相同效果:

want <- have %>%
  mutate(across(a1:c2, ~ ifelse(. == 1, as.numeric(id), NA_real_)))

结果验证

运行修正后的代码,得到的结果与预期输出完全一致:

# 预期输出
want_expected <- structure(list(a1 = c(1, 2, NA, 4, 5, 6, 7, 8, 9, 10), a2 = c(1, 
2, NA, 4, 5, NA, 7, 8, 9, 10), b1 = c(NA, NA, NA, NA, NA, 6, NA, NA, NA, 
NA), b2 = c(1, 2, NA, NA, NA, 6, NA, NA, NA, NA), c1 = c(NA, NA, NA, NA, 
5, NA, NA, NA, NA, NA), c2 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), id = 1:10), 
row.names = c(NA,-10L), class = c("tbl_df", "tbl", "data.frame"))

# 检查是否一致
all.equal(want, want_expected)
# [1] TRUE

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 11:15:26