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

如何修改for循环实现每次随机移除完整Transect并计算类别频率?

问题

我有一个较大的数据集,当前用for循环每次移除每个Transect的一行,并计算Category的频率。现在想改成每次迭代随机移除整个Transect(比如第一次移除所有Transect 3,第二次移除所有Transect 1)。以下是示例数据集和现有代码,请问怎么实现?

示例数据集

Transect <- c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3)
Category <- c("S","S","S","C","T","S","SP","T", "C", "T","S","SP","T","S","C")
dat <- data.frame(Transect,Category)

现有代码

for (q in 1:2) {
  
  for ( i in 0:5){
    #if (i>0)
    
    df <- dat2 %>%
      group_by(Transect) %>%
      sample_n(n() - i, replace = TRUE) %>%
      ungroup()
    
    c <- df %>%                               
      group_by(Category) %>%
      summarise(n = n(), replace=TRUE) %>%
      mutate(freq = n / sum(n), 
             total=55-i) 
    if (i==0){
      tot_1=c
    } else {
      tot_1=bind_rows(tot_1,c)
    }
  }
  tot_1$rep = q 
  if (q==1){
    dftot = tot_1
  } else {
    dftot=bind_rows(dftot, tot_1)
  }
}
解决方案

要实现每次迭代随机移除整个Transect,核心是随机选定要移除的Transect组,保留剩余数据后计算频率。以下是两种适配需求的修改方案:


方案1:遍历移除0到多个Transect的情况

该方案保留原代码的迭代逻辑,将“按行移除”改为“按Transect组移除”,可灵活控制每次移除的Transect数量:

library(dplyr)

# 配置参数:重复次数、每次最多移除的Transect数量
n_reps <- 2
max_remove <- length(unique(dat$Transect)) - 1  # 至少保留1个Transect
all_transects <- unique(dat$Transect)

# 初始化结果集
dftot <- data.frame()

for (q in 1:n_reps) {
  tot_1 <- data.frame()
  
  # 遍历移除0个(全保留)到max_remove个Transect的情况
  for (i in 0:max_remove) {
    if (i == 0) {
      df <- dat
    } else {
      # 随机选择i个要移除的Transect
      removed <- sample(all_transects, size = i, replace = FALSE)
      df <- dat %>% filter(!Transect %in% removed)
    }
    
    # 计算Category频率
    freq_df <- df %>%                               
      group_by(Category) %>%
      summarise(n = n()) %>%
      mutate(freq = n / sum(n), 
             total_rows = nrow(df),
             removed_transect_num = i)
    
    tot_1 <- bind_rows(tot_1, freq_df)
  }
  
  # 添加重复次数标记
  tot_1$rep <- q
  dftot <- bind_rows(dftot, tot_1)
}

# 查看最终结果
print(dftot)

方案2:每次固定移除1个Transect(贴合需求描述)

该方案更贴合你提到的“第一次移除Transect3,第二次移除Transect1”的场景,每次重复中依次随机移除单个Transect:

library(dplyr)

n_reps <- 2
all_transects <- unique(dat$Transect)
dftot <- data.frame()

for (q in 1:n_reps) {
  # 先记录全保留的情况
  tot_1 <- dat %>%                               
    group_by(Category) %>%
    summarise(n = n()) %>%
    mutate(freq = n / sum(n), 
           total_rows = nrow(dat),
           removed_transect = "None",
           removed_count = 0)
  
  # 随机打乱Transect顺序,依次移除每个
  shuffled_transects <- sample(all_transects)
  for (transect in shuffled_transects) {
    df <- dat %>% filter(Transect != transect)
    
    freq_df <- df %>%                               
      group_by(Category) %>%
      summarise(n = n()) %>%
      mutate(freq = n / sum(n), 
             total_rows = nrow(df),
             removed_transect = as.character(transect),
             removed_count = 1)
    
    tot_1 <- bind_rows(tot_1, freq_df)
  }
  
  tot_1$rep <- q
  dftot <- bind_rows(dftot, tot_1)
}

print(dftot)

代码说明

  1. 核心逻辑:用sample()随机选定要移除的Transect组,通过filter()筛选剩余数据,替代原代码按行移除的逻辑。
  2. 结果标记:新增removed_transect(被移除的Transect编号)、removed_count(移除数量)等字段,方便后续区分不同迭代的结果。
  3. 重复处理:保留原代码的重复次数逻辑,将多次重复的结果合并到总数据集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 14:35:45