我可以在 R 中重新洗牌嵌套 tibble 中的数据吗?

Can I reshuffle data in nested tibble in R?

提问人:monkparakeet 提问时间:10/18/2023 最后编辑:Markmonkparakeet 更新时间:10/19/2023 访问量:55

问:

我希望能够随机化每个“对”何时(“date.time”)出现“类型”,并最终为排列参考模型重复此过程 10,000。

当我在寻找解决方案时,我遇到了这个例子作为灵感。我的印象是,这段代码会为每对使用适当数量的 types/date.times 重新采样 tibble。

我认为我误解了 n_sample() 函数的作用,并且我对如何操作嵌套数据的理解有限。我不想重新洗牌该类型的顺序,并且 date.time 出现在 tibble 中,而是想为每对的类型重新分配一个随机的 date.time。重要的是,type 和 date.time 特定于特定对

以下是我的 for 循环的一次迭代的简化尝试:

我有一个这样的df:

df <- data.frame(pair=c("AB", "AB", "AB", "AB", "CD", "CD", "DE", "DE", "DE"), 
                 type=c("PR", "NN", "AP", "PX", "BK", "PX", "NN", "NN", "S2"),
                 date.time=c("2021-04-05_17:50:42", "2021-04-05_17:00:03", "2021-04-05_15:36:00", "2021-04-05_15:20:13", "2021-04-05_16:40:14", "2021-04-05_16:11:21", "2021-04-05_17:00:03", "2021-04-05_16:40:14", "2021-04-05_17:00:03"))

我确定了每对的“样本”数量或出现的类型数量:

sample.sizes <- df  %>% 
                  dplyr::group_by(pair) %>%  
                  dplyr::summarize(n.sample = n()) %>%
                  ungroup()

我嵌套了数据并绘制了样本:

nested_data <- df  %>%
       select(pair, type, date.time) %>%
       group_by(pair) %>%   
       nest() %>%  # --> one row per relationship
       ungroup() %>% 
       arrange(pair) %>%
       merge(sample.sizes, by = "pair")


 sampled_obsdata <- nested_obsdata %>%
                  mutate(sample = purrr::map2(data, n.sample, n_sample))

data <- sampled_obsdata %>% 
                          select(-data) %>%
                          unnest(sample) %>%
                          arrange(pair, date.time)

我希望我的问题和理想的结果是明确的 - 我是第一次发帖,所以对我放轻松!谢谢!

r 随机 嵌套列表

评论


答:

0赞 Brian Syzdek 10/18/2023 #1

我想我听到你说你想从同一对组中的随机采样值生成一个新的 date.time 值,所以其中 pair 是“AB”有 4 个值,其中任何一个值都可以为每行的新 date.time 值选择“AB”作为对?如果是这样,您可以group_by配对、变异和采样,以创建已从该组采样的新变量。目前尚不清楚每个新的 date.time 值是否必须是唯一的,或者它是否可以重复,以及如果旧的 date.time 和新的 date.time 可以相同,是否可以。假设这些不是约束,您可以执行以下操作:

library(dplyr)
df %>% group_by(pair) %>% mutate(new_date = sample(date.time)) %>% ungroup

它给出了这样的内容:

# A tibble: 9 × 4
  pair  type  date.time           new_date           
  <chr> <chr> <chr>               <chr>              
1 AB    PR    2021-04-05_17:50:42 2021-04-05_17:00:03
2 AB    NN    2021-04-05_17:00:03 2021-04-05_15:36:00
3 AB    AP    2021-04-05_15:36:00 2021-04-05_17:50:42
4 AB    PX    2021-04-05_15:20:13 2021-04-05_15:20:13
5 CD    BK    2021-04-05_16:40:14 2021-04-05_16:11:21
6 CD    PX    2021-04-05_16:11:21 2021-04-05_16:40:14
7 DE    NN    2021-04-05_17:00:03 2021-04-05_16:40:14
8 DE    NN    2021-04-05_16:40:14 2021-04-05_17:00:03
9 DE    S2    2021-04-05_17:00:03 2021-04-05_17:00:03

编辑:根据下面的注释,要在组中没有任何重复的新日期,并且没有new_date匹配 date.time,您可以先采样,然后重新采样,直到满足约束条件。根据数据的大小和组数,您可以成对嵌套,然后循环访问,直到满足每个组的条件。如果您的数据更复杂,我会为每个组保留一组 date.time 值,然后逐行删除每个采样值,不允许样本值与 date.time 值匹配,否则这将需要一段时间,因为您不太可能在组中的至少一行中找不到匹配的新旧日期值。

下面显示了如何对整个数据执行操作。如注释中所述,对于组 DE,您的约束是不可能的,该组具有保证new_date与 date.time 匹配的数据。我过滤掉了:

partial_df <- df %>% filter(pair != "DE")
repeat({
    # Sample date.time for each group a shown,
    partial_df <- partial_df %>% 
        group_by(pair) %>% 
        mutate(new_date = sample(date.time)) %>% 
        ungroup()
    
    #  then break when all the new_date values do not match date.time
    if(partial_df %>% summarise(all(new_date != date.time)) %>% pull()){
        # add return(df) here if nesting, and just include mutate above
        break()
    } 
})

评论

0赞 monkparakeet 10/19/2023
感谢您的这个和澄清问题!这看起来像是我问题的一个很好的解决方案。我想在不替换的情况下进行采样,因此一旦对 date.time 进行了采样,就无法再次对特定对组进行采样。我想我可以用 replace = FALSE 来完成这个任务吗?如果我想确保旧的和新的date.times不能相同,我怎么能做到这一点?
0赞 Brian Syzdek 10/19/2023
由于您的数据是这样的,因此无法获取与 date.time 不匹配的 new_date 值,因为在组 DE 中,三个值中有两个相同的 date.time 值,这保证了一个 date.time 值将始终与new_date匹配。是的,要不进行替换,请设置 replace = FALSE,这是默认值。我编辑了我的答案,以显示满足额外限制的方法。
0赞 monkparakeet 10/26/2023
感谢您的更新,但我遇到了与之前相同的问题,这就是我使用嵌套数据解决方案的原因。我认为问题之所以出现,是因为我需要每对不同数量的样本。我想知道您是否知道如何编辑我的代码,以便它仅对嵌套数据中的 date.time 列进行采样,而不是对所有行进行采样。我对结构不够熟悉,无法成功从当前格式获取采样数据。