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

如何用嵌套循环存储双因子变量组合的计算结果

按因子变量组合计算并存储结果

现有数据与函数

数据定义

df <- data.frame(SPECIES = as.factor(c(rep("SWAN",10), rep("DUCK",4), rep("GOOS",12),
                             rep("PASS",9), rep("FALC",10))),
                 DRAINAGE = as.factor(c(rep(c("Central", "Upper", "West"),15))),
                 CATCH_QTY = c(1,1,2,5,6,1,2,1,1,1,1,1,3,1,1,2,1,1,2,2,
                               rep(1,25)),
                 TAGGED = c(rep("T",6),NA,"T","T",NA,rep("T",10),NA,NA,
                            rep("T",9),NA,"T","T","T","T",NA,rep("T",7),NA),
                 RECAP = c(rep(NA,6),"RC",NA,NA,"RC",rep(NA,10),"RC","RC",
                            rep(NA,9),"RC",NA,NA,NA,NA,"RC",rep(NA,7),"RC"))

自定义计算函数

myfunction <- function(dat, yr, spp, drain){
  dat <- dat %>% filter(SPECIES == spp, DRAINAGE == drain)

    estimatea <<-
      dat %>%
      summarise(NumCaught = sum(CATCH_QTY, na.rm = T),
            NewTags = sum(!is.na(TAGGED)), 
            Recaps = sum(!is.na(RECAP)),
            TotTags = sum(NewTags+Recaps))
    
    dataTest1 <- cbind(yr, spp, drain, estimatea$NumCaught, estimatea$NewTags,
                       estimatea$Recaps, estimatea$TotTags)
}

尝试的方法及报错

嵌套循环尝试

第一种循环写法:

out <- list()

for (i in seq_along(levels(df$SPECIES))) {
  for (j in seq_along(levels(df$DRAINAGE))) {
    out[i,j] <- myfunction(df, "2023", i, j)
  }
}

报错:

Error in out[i, j] <- myfunction(df, "2023", i, j) :
incorrect number of subscripts on matrix

调整索引后的循环写法:

for (i in seq_along(levels(df$SPECIES))) {
  for (j in seq_along(levels(df$DRAINAGE))) {
    out[i+1,j+1] <- myfunction(df, "2023", i, j)
  }
}

报错信息同上。

非循环方法尝试

combos <- expand.grid(df$SPECIES, df$DRAINAGE) %>% distinct() %>%
  drop_na() %>% rename(spp = Var1, drain = Var2)
test <- myfunction(df, "2023", combos$spp, combos$drain) #结果不正确

sapply(combos$spp, function(x) mapply(myfunction,x,combos$drain))
apply(combos, 2, FUN = myfunction)

报错:

Error in UseMethod("filter") :
no applicable method for 'filter' applied to an object of class "character"

理想输出格式

desired_out <- data.frame(yr = rep("2023",3),
                          spp = c("DUCK", "DUCK", "GOOS"),
                          drain = c("West", "Central", "Upper"),
                          V4 = c(1,3,4),
                          V5 = c(1,1,3),
                          v6 = c(0,0,1),
                          V7 = c(1,1,4))

解决方案

第一步:修正自定义函数

原函数存在全局赋值冗余、返回矩阵而非数据框、TotTags计算冗余三个问题,修正后:

library(dplyr)

myfunction <- function(dat, yr, spp, drain){
  dat %>%
    filter(SPECIES == spp, DRAINAGE == drain) %>%
    summarise(yr = yr,
              spp = spp,
              drain = drain,
              NumCaught = sum(CATCH_QTY, na.rm = TRUE),
              NewTags = sum(!is.na(TAGGED)), 
              Recaps = sum(!is.na(RECAP)),
              TotTags = NewTags + Recaps)
}

方法一:修正嵌套循环

直接遍历因子水平值而非索引,用列表存储结果后合并:

# 获取所有因子水平
spp_levels <- levels(df$SPECIES)
drain_levels <- levels(df$DRAINAGE)

out_list <- list()
counter <- 1

for (spp in spp_levels) {
  for (drain in drain_levels) {
    # 跳过无数据的组合(可选)
    if(nrow(filter(df, SPECIES == spp, DRAINAGE == drain)) == 0) next
    out_list[[counter]] <- myfunction(df, "2023", spp, drain)
    counter <- counter + 1
  }
}

# 合并为最终数据框
final_out <- bind_rows(out_list)

方法二:用purrr实现无循环映射

生成所有有效组合后批量调用函数:

library(purrr)
library(dplyr)

# 生成所有非空的因子组合
combos <- expand.grid(spp = levels(df$SPECIES), 
                      drain = levels(df$DRAINAGE)) %>%
  filter(pmap_lgl(., ~nrow(filter(df, SPECIES == ..1, DRAINAGE == ..2)) > 0))

# 批量计算并合并结果
final_out <- pmap_dfr(combos, ~myfunction(df, "2023", ..1, ..2))

方法三:直接用dplyr分组计算(最简洁)

无需循环或自定义函数,直接分组汇总:

final_out <- df %>%
  group_by(SPECIES, DRAINAGE) %>%
  summarise(yr = "2023",
            NumCaught = sum(CATCH_QTY, na.rm = TRUE),
            NewTags = sum(!is.na(TAGGED)), 
            Recaps = sum(!is.na(RECAP)),
            TotTags = NewTags + Recaps) %>%
  rename(spp = SPECIES, drain = DRAINAGE) %>%
  ungroup()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:55:59