【问题标题】:Randomly subsampling a dataframe without replacements in a specific column with R使用 R 在特定列中随机对数据帧进行二次采样而不进行替换
【发布时间】:2021-12-08 14:33:28
【问题描述】:

我有一个具有这种结构的数据框:

> df
factor  y  x
1       2  0
1       3  0
1       1  0
1       2  0
2       3  0
2       1  0
2       3  1
3       4  1
3       3  1 
3       6  3
3       5  2
4       4  1
4       7  8
4       2  1
2       5  3

在实际数据集中,我有 200 行和不同的变量:几个连续变量和一个因子变量,有 70 个级别,每个级别最多 4 个观察值。

我想将我的整个数据帧随机分成 4 个大小相等的组,而无需在每个组内仅在因子变量中进行替换。换句话说,我希望因子变量的每个级别每组不超过一次。

我尝试了不同的解决方案。 例如,我尝试将“因子”变量分成四组而不进行替换,如下所示:

factor1 <- as.character(df$factor)

set.seed(123)
group1 <- sample(factor, 35,replace = FALSE) 

factor2 <- setdiff(factor1, group1) 
group2 <- sample(factor2, 35,replace = FALSE) 

# and the same for "group3" and "group4"

但是我不知道如何将组向量(group1、group2 等)与我的 df 中的其他变量('x' 和 'y')相关联。

我也试过:

group1 <- sample_n(df, 35, replace = FALSE)

但是这个解决方案也失败了,因为我的数据框不包含重复的行。唯一重复的值在因子变量中。

最后,我尝试使用在回答类似问题here时提出的解决方案,适应我的情况:

random.groups <- function(n.items = 200L, n.groups = 4L,
                          factor = rep(1L, n.items)) {

  splitted.items  <- split(seq.int(n.items), factor)

  shuffled <- lapply(splitted.items, sample)

  1L + (order(unlist(shuffled)) %% n.groups)
}

df$groups <- random.groups(nrow(df), n.groups = 4)

但是,生成的 4 组包含重复的因子变量值,因此某些东西无法正常工作。

我非常感谢任何解决此问题的想法或建议!

【问题讨论】:

  • 使用 dplyr() : new_df % group_by(factor) %>% sample_n(35)。请提供示例输出以了解更多详细信息。

标签: r dataframe sampling


【解决方案1】:

一种方法是按因子分组,创建因子长度的变量,按大小和长度排列。最后,您为第一、第二、第三和第四行分配一个组。然后,您可以使用此变量进行过滤。

library(dplyr)
df <- data_frame(factor = c(1,1,1,1,2,2,2,3,3,3,3,4,4,4,2),
                 x = floor(runif(15, min=0, max=20)),
                 y = floor(runif(15, min=211, max=305)))
df <- df %>% group_by(factor) %>% mutate(size = length(factor)) %>% arrange(desc(size), factor) %>% 
  ungroup() %>%  mutate(group = ifelse(row_number() %% 4 == 1, "A",
                                       ifelse(row_number() %% 4 == 2, "B",
                                              ifelse(row_number() %% 4 == 3, "C", "D"))))

【讨论】:

    【解决方案2】:

    一个data.table 解决方案演示了一个稍大的数据集:

    library(data.table)
    
    dt <- setorder(data.table(factor = sample(10, 44, TRUE), x = runif(44), y = runif(44)), factor)
    numGroups <- 4L
    maxFactor <- max(dt$factor)
    dt2 <- setorder(
      setorder(
        dt[sample(.N, .N)], # randomly reorder the data
        factor              # sort by factor
      )[, temp := cumsum(.I > 0), by = factor] # create a column to keep a running count of the occurrence of each factor
      [temp <= numGroups]                      # remove rows that can't go in a group due to factor exclusion
      [sample(.N, .N) <= (.N %/% numGroups)*numGroups] # randomly remove excess rows (keep the group sizes equal)
      [, temp := sample(10, 10)[factor]]               # randomly reorder factor groups
      [, grp := c(rep(1:numGroups, .N/numGroups))],    # assign each row a group: row 1 -> group 1, row 2 -> group 2 ... 5 -> 1, 6 -> 2, etc.
      grp # sort by group for table readability
    )[, temp := NULL] # remove the temporary column
    

    生成的data.table 将具有numGroups 组,如grp 列所示。每个组将具有相同的行数。为了满足无重复因子约束,每组中的行数将是最大可能的。对于较小的样本,请抽取dt2 的子样本(请参阅this question)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-22
      • 2011-01-07
      • 1970-01-01
      相关资源
      最近更新 更多