如何使用purrr map2将嵌套数据中的if-then转为case_when?
用purrr::map2结合case_when处理嵌套数据的条件映射
嘿,我来帮你搞定这个需求!要把嵌套数据里的if-then逻辑转成case_when,同时用purrr::map2来逐行处理你的嵌套列,咱们可以分步骤来实现:
首先,先把你的原始数据整理成更易读的形式:
library(tidyverse) # 你的原始数据 vec1 <- c("A", "B") vec2 <- c("A", "B", "C") df1 <- structure( list( A = c("X", "Y"), data = list( tibble(B = c(4L, 9L)), tibble(B = c(5L, 2L, 8L, 2L)) ), C = list(c("A", "B"), c("A", "B", "C")) ), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -2L) )
核心思路
我们需要遍历df1的每一行,对每行的data(嵌套表格)和C(条件类别向量)完成两个核心操作:
- 根据
C的类别数量,把data$B的值划分成对应数量的区间 - 用
case_when把每个区间的B值映射到C里的对应类别
为了灵活适配不同长度的C(比如有的是2个类别,有的是3个),我们会动态生成case_when的条件,避免手动写死逻辑。
实现代码
先定义一个处理单组嵌套数据的函数,再用map2批量应用到所有行:
# 定义处理单个嵌套表格和对应类别向量的函数 process_nested_data <- function(data_tbl, category_vec) { # 获取当前组的类别数量 n_categories <- length(category_vec) # 根据B列的数值分布生成区间分割点(这里用分位数均匀划分,你可以改成固定区间) value_breaks <- quantile(data_tbl$B, probs = seq(0, 1, length.out = n_categories + 1)) # 动态生成case_when的条件-结果对 case_conditions <- map2( 1:n_categories, category_vec, ~ { # 最后一个区间用左开右闭,避免边界值重复匹配 if (.x == n_categories) { between(data_tbl$B, value_breaks[.x], value_breaks[.x + 1], left = FALSE) ~ .y } else { between(data_tbl$B, value_breaks[.x], value_breaks[.x + 1]) ~ .y } } ) # 应用case_when并返回处理后的表格 data_tbl %>% mutate(category = case_when(!!!case_conditions)) } # 用map2遍历data和C列,生成处理后的嵌套列 df1_processed <- df1 %>% mutate(processed_data = map2(data, C, process_nested_data))
查看处理结果
你可以展开processed_data列查看每一组的处理效果:
# 查看第一行的处理结果 df1_processed$processed_data[[1]] #> # A tibble: 2 × 2 #> B category #> <int> <chr> #> 1 4 A #> 2 9 B # 查看第二行的处理结果 df1_processed$processed_data[[2]] #> # A tibble: 4 × 2 #> B category #> <int> <chr> #> 1 5 B #> 2 2 A #> 3 8 C #> 4 2 A
代码细节解释
map2(data, C, process_nested_data):同时遍历data和C两个列表列,把每一对对应的数据传入处理函数,保证每行的嵌套表格和类别向量一一对应- 动态生成
case_when条件:用map2生成每个区间对应的条件-结果对,再用!!!(非标准求值语法)把这些条件注入到case_when中,自动适配不同长度的类别向量 - 区间划分逻辑:这里用
quantile均匀划分B的值域,如果你需要固定区间(比如c(0,3,6,10)),只需要修改value_breaks的生成逻辑即可
内容的提问来源于stack exchange,提问作者Geet
相关产品推荐
相关产品推荐

