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

如何在R中无重叠地打乱时间序列中的时间块?

问题描述

我们有包含3个个体的活动时间序列数据,需要对每个个体的时间块进行随机打乱,需满足以下要求:

  • 个体内的时间块无重叠
  • 所有打乱后的时间块必须完全处于原时间线范围内(示例中为1到30)
  • 个体间的时间块可以重叠

示例数据框如下:

library(tidyverse)
GrXX <- tibble(Individual = rep(c("A", "B", "C"), times = c(2, 3, 5)),
               Frame_beginning = c(1, 16, 7, 21, 29, 3, 9, 12, 19, 27),
               Frame_end = c(3, 22, 15, 24, 30, 7, 10, 12, 24, 30),
               Duration = Frame_end - Frame_beginning + 1,
               Frame_end_valid_group = 30)
现有代码的问题

原代码采用"先放大块、再依次放小块"的循环逻辑,但存在以下缺陷:

  • 逻辑复杂,易出现索引错误(如valid_frames_2未定义、排序后数组索引不匹配)
  • 无法彻底避免个体内重叠,极端情况下可能出现无有效位置可供放置的情况
  • 随机化分布不均匀,小块的位置选择被大块严重限制
高效解决方案

采用间隙随机分配法,通过计算个体时间块的总占用时长,将剩余空闲时间随机分配为块之间的间隙,直接生成所有块的无重叠随机位置。此方法无需循环逐个放置,效率更高且能严格满足所有要求。

实现代码

# 定义单个个体的时间块打乱函数
shuffle_individual_blocks <- function(df, max_frame) {
  durations <- df$Duration
  n_blocks <- nrow(df)
  
  # 计算总占用时长与总空闲时长
  total_used <- sum(durations)
  total_free <- max_frame - total_used
  
  # 生成n_blocks+1个随机间隙(首尾+块之间),总和为total_free
  if (total_free > 0) {
    # 通过随机分割空闲时长得到间隙
    split_points <- sort(sample(1:total_free, n_blocks))
    gaps <- diff(c(0, split_points, total_free + 1)) - 1
  } else {
    # 无空闲时间时,所有间隙为0
    gaps <- rep(0, n_blocks + 1)
  }
  
  # 计算每个块的打乱后起止位置
  starts <- cumsum(c(gaps[1] + 1, durations[-n_blocks] + gaps[-c(1, n_blocks + 1)]))
  ends <- starts + durations - 1
  
  # 返回添加打乱后时间的数据集
  df %>%
    mutate(
      Frame_beginning_shuffled = starts,
      Frame_end_shuffled = ends,
      .after = Frame_end
    )
}

# 对每个个体分组执行打乱操作
GrXX_shuffled <- GrXX %>%
  group_by(Individual) %>%
  group_modify(~shuffle_individual_blocks(.x, max_frame = .x$Frame_end_valid_group[1])) %>%
  ungroup()

方法说明

  1. 间隙计算:将总空闲时长随机分配为n_blocks+1个间隙(包含首尾空闲区域),确保间隙总和等于总空闲时长
  2. 位置生成:通过累加间隙和前一个块的时长,直接计算每个块的起始位置,保证块之间无重叠且所有块都在有效时间线内
  3. 分组处理:利用group_by+group_modify实现对每个个体的独立处理,符合tidyverse风格

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:47:34