使用tidyverse将tibble的c3列与向量元素相乘生成多个新tibble
原始数据
创建目标tibble的代码:
c1 <- c(1,2,3) c2 <- c(4,5,6) c3 <- c(7,8,9) d1 <- as_tibble(data.frame(c1,c2,c3))
tibble结构如下:
A tibble: 3 × 3c1 c2 c3
1 1 4 7
2 2 5 8
3 3 6 9
用于相乘的向量:
v1 <- c(1,2,3)
需求说明
需要用tidyverse方法,将d1的c3列与v1中的每个元素相乘,生成三个独立的tibble,每个tibble的c3列对应原数值乘以v1中的一个元素,预期结果如下:
A tibble: 3 × 3c1 c2 c3
1 1 4 7
2 2 5 8
3 3 6 9
A tibble: 3 × 3c1 c2 c3
1 1 4 14
2 2 5 16
3 3 6 18
A tibble: 3 × 3c1 c2 c3
1 1 4 21
2 2 5 24
3 3 6 27
尝试的代码及问题
尝试使用outer()生成乘积,但结果是单个包含矩阵列的tibble,不符合tidy原则,也未生成独立对象:
d1 %>% mutate(outer(c3, v1, FUN = "*"))
得到的结果:
A tibble: 3 × 4c1 c2 c3 `outer(c3, v1, FUN = "*")`[,1] [,2] [,3]
1 1 4 7 7 14 21
2 2 5 8 8 16 24
3 3 6 9 9 18 27
解决方案
以下是两种符合tidyverse风格的最优方法:
方法1:用map()生成包含多个tibble的列表
利用purrr包的map()函数遍历v1的每个元素,对d1进行修改,最终得到一个包含三个目标tibble的列表:
library(tidyverse) result_list <- map(v1, ~ d1 %>% mutate(c3 = c3 * .x))
通过result_list[[1]]、result_list[[2]]、result_list[[3]]可分别获取每个独立的tibble。
方法2:交叉连接+嵌套拆分(适合批量处理)
先通过交叉连接将v1和d1合并,计算修改后的c3,再按乘数分组嵌套,最后提取每个组的tibble:
result_list <- tibble(multiplier = v1) %>% crossing(d1) %>% mutate(c3 = c3 * multiplier) %>% group_by(multiplier) %>% nest() %>% pull(data)
同样得到包含三个tibble的列表,便于后续批量操作。
可选:生成独立命名对象
如果需要直接生成三个独立的全局变量(如d1_1、d1_2、d1_3),可结合map2()和assign():
names <- str_c("d1_", v1) map2(names, v1, ~ assign(.x, d1 %>% mutate(c3 = c3 * .y), envir = globalenv()))
执行后环境中会出现三个独立的tibble对象,对应不同乘数的结果。
内容的提问来源于stack exchange,提问作者Jacob

