【问题标题】:How to create a dataframe with repeated columns created from randomly sampling another dataframe?如何创建一个数据框,其中包含通过随机抽样另一个数据框创建的重复列?
【发布时间】:2021-04-01 16:03:40
【问题描述】:

我正在尝试使用来自另一个数据帧的随机抽样重复向数据帧添加列。

我的第一个包含要从中采样的实际数据的数据框看起来像这样

df <- data.frame(cat = c("a", "b", "c","a", "b", "c"),
                 x = c(6,23,675,1,78,543))

我有另一个这样的数据框:

df2 <- data.frame(obs =c(1,2,3,4,5,6,7,8,9,10),
                  cat=c("a", "a", "a", "b", "b", "b", "c","c","c", "c"))

我想向 df2 添加 1000 个新列,这些列从 df 中随机抽样,按 cat 分组。我想出了一种(可能是非常业余的)方法,通过使用 slice_sample() 使用 df 的随机样本创建一个新的数据帧 sample1,然后将 sample1 与 df2 合并。

df <- df %>%
  group_by(cat)

df2 <- df2 %>%
  group_by(cat)

sample1 <- slice_sample(df, preserve = T, n=3, replace = T )
sample1 <- sample1 %>%
  ungroup() %>%
  mutate(obs=c(1:9)) %>%
  select(-cat)

df3 <- merge(df2,sample1, by= "obs")

现在,我想找到一种方法重复此操作 1000 次,最终得到具有 1000 列(x1、x2、x3 等)的 df3

我研究过重复循环,但无法弄清楚如何使上述代码在循环内工作。

【问题讨论】:

  • 我认为您可以将其包装在一个函数中并使用replicate(1000, call_your_fn)

标签: r dataframe loops random


【解决方案1】:

您只能在 df2 中保留 3 X 个唯一的 cat 值行。使用replicate 重复采样过程n 次并添加n 新列。

library(dplyr)

n <- 10
df2 <- df2 %>% slice(1:(3*n_distinct(cat)))

df2[paste0('x', 1:n)] <- replicate(n, df %>%
                                       group_by(cat) %>%
                                       slice_sample(n = 3, replace = TRUE) %>%
                                       pull(x))

#  obs cat  x1  x2  x3  x4  x5  x6  x7  x8  x9 x10
#1   1   a   6   1   1   6   6   1   1   1   6   6
#2   2   a   6   1   1   1   1   6   1   1   1   1
#3   3   a   1   6   1   6   1   6   6   1   6   6
#4   4   b  78  78  78  23  78  78  78  78  23  23
#5   5   b  78  78  78  23  23  23  78  78  78  23
#6   6   b  78  78  23  78  78  78  23  23  78  23
#7   7   c 675 543 543 543 543 543 675 543 543 675
#8   8   c 543 543 675 675 675 675 675 543 675 543
#9   9   c 543 543 675 543 675 543 675 675 543 675

【讨论】:

    【解决方案2】:

    这里有一个data.table 选项可能会有所帮助

    dt <- as.data.table(df)
    dt2 <- as.data.table(df2)
    n <- 1000
    res <- cbind(
      dt2[, .(obs)],
      dt2[
        ,
        replicate(n, sample(dt[.BY, x, on = "cat"], .N, replace = TRUE), simplify = FALSE),
        cat
      ]
    )
    

    【讨论】:

      【解决方案3】:

      一种选择是创建一个函数,然后在执行连接之前使用replicatererun(来自purrr

      library(dplyr)
      library(purrr)
      library(stringr)
      f1 <- function(dat1) {
                  dat1 %>%
                       group_by(cat) %>%
                       slice_sample(n = 3, replace = TRUE)  %>%
                           ungroup() %>%
                           mutate(obs = row_number()) %>%
                           select(-cat) 
               
            
            
            }
          
      n <- 10
      out <- rerun(10, f1(df)) %>% 
               c(list(df2), .) %>% 
               reduce(inner_join, by = 'obs') %>%  
                rename_at(vars(starts_with('x')), ~ str_c('x', seq_along(.)))  
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-07-01
        • 2018-08-20
        • 1970-01-01
        • 2015-05-18
        • 1970-01-01
        • 2020-08-04
        • 2018-12-30
        • 2021-09-23
        相关资源
        最近更新 更多