如何在tidyverse imap迭代中子集化列表,实现矩阵Inflow承接前序Outflow
问题解决:递推提取子列表内前序矩阵的Outflow列
核心问题分析
你的代码存在两个关键问题导致无法获取前序矩阵的Outflow列:
- 内层
imap中的matL是传入的原始字符向量(比如mat_One对应的c("Boy", "Cat")),不是已经生成的矩阵列表,所以matL[[index-1]]取到的是字符串而非之前计算出的矩阵。 - 代码中未定义
balVector,会直接触发报错,需要补充定义。
修正后的代码
使用purrr::accumulate替代内层imap,它能在迭代过程中传递前一个计算结果,完美实现递推逻辑:
library(tidyverse) matList <- list(mat_One = c("Boy", "Cat"), mat_Two = c("Boy", "Bat")) allocate <- list(mat_One = c(0.6, 0.5, 0.4), mat_Two = c(0.4, 0.5, 0.6)) flowVector <- c(6, 5, 600) rates <- list(mat_One = 0.10, mat_Two = 0.20) # 补充定义balVector(示例用flowVector替代,可根据实际需求修改) balVector <- flowVector createBucketMap <- function() { imap(matList, \(mat_group, group_name) { # 用accumulate递推生成矩阵列表 accumulate(mat_group, \(prev, current) { alc <- allocate[[group_name]] rate <- rates[[group_name]] Inflow <- if(is.null(prev)) { # 第一个元素,用初始flowVector计算 flowVector * alc } else { # 后续元素,提取前一个矩阵的Outflow列 prev[, "Outflow"] } Due <- balVector * alc * rate Outflow <- Inflow cbind(Inflow, Due, Outflow) }, .init = NULL) |> # 移除.init的NULL,保留实际生成的矩阵 discard(is.null) |> set_names(mat_group) }) } # 运行测试 createBucketMap()
关键修正点
- 递推逻辑实现:用
accumulate替代内层imap,prev参数会自动传入上一次迭代生成的矩阵,直接通过prev[, "Outflow"]提取目标列(矩阵支持通过列名字符串索引)。 - 初始值处理:通过
.init = NULL和discard(is.null)处理第一个元素的初始计算逻辑。 - 变量修复:补充了
balVector的定义,避免运行时触发未定义变量报错。
内容的提问来源于stack exchange,提问作者Curious Jorge - user9788072
相关产品推荐
相关产品推荐

