如何在R中用自定义函数、if_else与grep批量重编码数据值
解决方案
问题根源分析
你之前的代码无法批量运行,核心有两个问题:
- 封装函数时直接引用了
data$var,但across会把单列向量传递给函数,而非整个数据框,函数无法识别全局的data$var; if_else要求两个分支的返回值类型一致,用NULL会导致类型不匹配,应该用整数型的NA_integer_对应1。
通用自定义函数写法
根据你的需求(存在非空白字符则编码为1,否则标记NA),可以写一个接收列向量的函数:
encode_binary <- function(x) { # 匹配空字符串或全空格的条目,取反后赋值1,否则NA if_else(!grepl("^\\s*$", x), 1L, NA_integer_) }
如果需要严格匹配字母(和你原代码逻辑一致),可以把正则改成"[a-z]",加上ignore.case = TRUE也能匹配大写字母:
encode_binary <- function(x) { if_else(grepl("[a-z]", x, ignore.case = TRUE), 1L, NA_integer_) }
批量应用到指定列
用dplyr::mutate() + across()批量处理任意列范围,比如:
- 处理列名以
q开头的所有列:
library(dplyr) # 批量更新数据框 data <- data |> mutate(across(starts_with("q"), encode_binary))
- 处理指定列向量
variable中的列:
data <- data |> mutate(across(all_of(variable), encode_binary))
- 处理第3到第102列:
data <- data |> mutate(across(3:102, encode_binary))
无需自定义函数的简化写法
如果不想单独写函数,直接用匿名函数更高效:
data <- data |> mutate(across(all_of(variable), ~ if_else(!grepl("^\\s*$", .x), 1L, NA_integer_)))
测试示例
构造测试数据验证效果:
# 测试数据 set.seed(123) test_data <- tibble( id = 1:5, q1 = c("a", "", "b", " ", "c"), q2 = c("", "d", " ", "e", ""), q3 = c("f", "g", "", "", "h") ) # 处理后结果 test_data_processed <- test_data |> mutate(across(starts_with("q"), encode_binary))
输出结果:
# A tibble: 5 × 4 id q1 q2 q3 <int> <int> <int> <int> 1 1 1 NA 1 2 2 NA 1 1 3 3 1 NA NA 4 4 NA 1 NA 5 5 1 NA 1
内容的提问来源于stack exchange,提问作者Allison
相关产品推荐
相关产品推荐

