如果 for 循环内满足条件,如何重做样本?

问题描述 投票:0回答:1

我有一个边缘列表,其中包含有关二元交互的信息,包括有关交互类型(行为)和交互发生的日期时间戳(round.dt)的信息。

这里有一个例子:

# data
pd <- data.frame(dyad = c("A-B", "C-D", "E-F", "G-H", "I-E", "E-J", "K-F", "I-H", "L-M", "D-N", "A-B", "A-B"),
           round.dt = c("2021-04-06 10:40:00", "2021-04-06 15:30:00", "2021-04-16 14:20:00","2021-04-06 12:25:00", "2021-04-24 14:55:00", "2021-04-12 11:15:00",
 "2021-04-08 08:50:00","2021-04-16 09:25:00", "2021-04-19 17:20:00",
 "2021-04-24 09:30:00", "2021-04-06 10:40:00", "2021-04-19 17:20:00"),
 behavior = c("n" , "n" , "n" , "n","n", "n","n" , "n"  ,"b", "n", "a", "n"))

我编写了一个 for 循环,以便在每个二元体发生这些交互时重新洗牌(无论哪种行为)。此方法仅在二元交互发生时进行洗牌,但保留关系的身份(即无向二元的成员)、每个二元的每个行为观察到的关联总数以及二元交互的观察天数和时间。我认为这段代码按预期工作:

perms <-10
exp <-rep(NA, perms) 

# permutations
for (i in 1:perms) {
  d2rand <- 
    pd %>% 
      
    # shuffle times within dyad. 
    ## If there's only one interaction for a dyad, 
    ## the timestamp remains unchanged; otherwise, it's randomly shuffled
  
    group_by(dyad) %>% 
    mutate(round.dt = if(n() == 1) round.dt else sample(round.dt, n())) %>%   ## this does NOT constrain  one behavior every 5 minutes per r/ship. 
    ungroup() %>% 
  
    # classify behaviors as sp or ct 
    mutate(behav= ifelse(behavior== "n", "sp", "ct")) %>% 
    # get first case of each behavior within each dyad
    group_by(dyad, behav) %>% 
    summarize(first.time = min(round.dt), .groups= 'drop') %>% 
    pivot_wider(names_from = behav, values_from = first.time) %>% 
    ungroup() %>% 
    mutate(assoc.first= case_when(
      sp< ct~ TRUE,
      sp> ct~ FALSE,
      sp== ct~ FALSE,
      is.na(sp) & !is.na(ct) ~ FALSE,
      !is.na(sp) & is.na(ct) ~ TRUE,
      TRUE ~ NA))
  
  # what is probability that sp comes first?
  exp[i] <- mean(d2rand$assoc.first)
  
  print(paste(i,"of", perms))
  
}

问题在于(取决于每个二元交互的频率和时间),相同的行为可能会同时发生多次。例如,通过重新排列 round.dt dyad A-B,我可以得到一个迭代,显示 n 在同一 round.dt 中出现两次(2021-04-06 10:40:00)(表明这些事件同时发生)。

# Dyad A-B's observed interactions:
pd %>% filter(dyad == "A-B")

我想更新这个循环,以便相同的行为 (n) 不能同时发生。如果不同的行为(n,a)同时发生也没关系。如果他们这样做,我希望循环再次采样,直到没有模拟事件。

我希望我可以在示例后面添加一个内部(可能是 while-)循环,该循环检查每个二元组是否有重复的行。但我不知道如何实现这一点。

r for-loop permutation sample
1个回答
0
投票

我们可以定义一个小辅助函数,它检查向量

x
的洗牌是否会导致分组因子
g
内出现任何重复值,如果是这样,则继续洗牌:

keep_shuffling <- function(x, g) {
  if (length(x) == 1) return(x)
  x <- sample(x)
  if (any(table(x, g) > 1)) x <- keep_shuffling(x, g)
  return(x)
}

然后更换

mutate(round.dt = if(n() == 1) round.dt else sample(round.dt, n()))

mutate(round.dt = keep_shuffling(round.dt, behavior))
© www.soinside.com 2019 - 2024. All rights reserved.