【问题标题】:R function that evenly splits observations into groupsR 函数将观察结果均匀地分组
【发布时间】:2019-09-06 19:03:30
【问题描述】:

我有一个 30 x 2 数据框 (df),其中一列包含 30 个人的姓名,第二列包含他们的 ID#。 我想在 R 中创建一个函数,将 30 个人随机和最均匀地分成组,并且可以处理有和没有余数的除法。

为了澄清,这个函数将:

• 将 2 个参数作为参数:df 和一个表示组数的整数 • 将原始 df 还给我,但有一个额外的列,其中包含每个人随机分配到的组号 • 如果人数(行)数不能除以给定的整数,则其余行应在组之间尽可能均分

例如: • 如果我想将 30 人分成 1 个组,我的函数应该返回 df,其中包含一个新列“group_no”,每个人都有 1 个(每个人将被分配到同一个组)

• 如果我想要 4 个组,我希望看到 10 人被分配到 2 个组,其余 5 人被分配到另外 2 个组。

• 如果我想要 8 组,那么函数应该给我 6 组 4 人和 2 组 3 人,依此类推。

我已经编写了一些代码来满足我的需要,但我只是手动输入组,所以不仅仅是随机或正确的......我想将所有这些写在一个可以自动执行的函数中执行这些任务:

#My code so far
#For 1 group of 30 people

people=1:30
groups=1
df$group_no <- print(sample(groups))

#For 4 groups (2 groups of 10 people and 2 groups of 5 people)
groups=c(rep(1,5), rep(2,5), rep(3,10), rep(4,10))
df$group_no <- print(sample(groups))

#For 7 groups (3 groups of 6 people and 4 groups of 3 people)
groups=c(rep(1,6), rep(2,6), rep(3,6), rep(4,3), rep(5,3), rep(6,3), rep(7,3))
df$group_no <- print(sample(groups))

#For 8 groups (6 groups of 4 people and 2 groups of 3 people)
groups=c(rep(1,4), rep(2,4), rep(3,4), rep(4,4), rep(5,4), rep(6,4), rep(7,3), rep(8,3))
df$group_no <- print(sample(groups))


#For 10 groups of 3 people each
groups=c(rep(1,3), rep(2,3), rep(3,3), rep(4,3), rep(5,3), rep(6,3), rep(7,3), rep(8,3), rep(9,3), rep(10,3))
df$group_no <- print(sample(groups))


fct_grouping <- function(df, nr_groups) {
 ????? 
}

【问题讨论】:

  • 您对 7-7-8-8 的看法是完全正确的,我实际上刚刚意识到我的错误,并且正在纠正它。事实上,对于 7 组示例,我应该有 5 组 4 组和 2 组 5 组。但是对于 6-6-9-9,我想我不希望这样,因为我正在尝试分配人员尽可能平均地分配给小组。所以,我试图形成小组,使他们包含几乎相同数量的人。希望这是有道理的。

标签: r grouping combinatorics


【解决方案1】:

此功能使组大小尽可能接近,并随机分配组。


grouper <- function(df, n) {

  # create a random number for each row
  random <- sample(1:nrow(df), replace = FALSE, nrow(df))

  # divide the random number by the group size
  df$group_number <- ceiling(random / (nrow(df) / n))

  return(df)  
}

【讨论】:

  • Lief Esbenshade,非常感谢您的帮助,这实际上非常适合我想要做的事情! :)
  • 谢谢,如果它是您问题的最佳解决方案,请随时接受此答案。
【解决方案2】:

以下代码应该按照您的要求执行并返回一个包含分组的向量。

fct_grouping <- function(df, nr_groups) {
    base_number <- floor(nrow(df) / nr_groups)
    rest <- nrow(df) - base_number * nr_groups
    groupings <- sort(c(rep(seq(nr_groups), base_number), if (rest==0) numeric() else seq(rest)))
    return(groupings)
}

【讨论】:

  • 谢谢apeqqut!
【解决方案3】:

我确信您正在寻找的内容在数学上应该可以在 R 中编程,但是很难对剩余人数不等于 0 的组数的情况进行建模,因为存在分配案例的选项超过 1 个(考虑定义 10 组或更多组的数量)。此外,您制作的示例不符合您要求的条件(最相似的组大小)。 这是我能想到的最接近的事情:

df <- data.frame(people = c(1:30))

fct_grouping <- function(df, nr_groups) {

if (nrow(df) %% nr_groups == 0) {
print(cbind(df, sample(nr_groups)))

} else {
print("n is not a multiple of number of people")
}}

df2 <- fct_grouping(df, 5)

#         people sample(nr_groups)
# 1       1                 1
# 2       2                 3
# 3       3                 2
# 4       4                 5
# 5       5                 4
# 6       6                 1
# 7       7                 3
# 8       8                 2
# 9       9                 5
# 10     10                 4
# 11     11                 1
# 12     12                 3
# 13     13                 2
# 14     14                 5
# 15     15                 4
# 16     16                 1
# 17     17                 3
# 18     18                 2
# 19     19                 5
# 20     20                 4
# 21     21                 1
# 22     22                 3
# 23     23                 2
# 24     24                 5
# 25     25                 4
# 26     26                 1
# 27     27                 3
# 28     28                 2
# 29     29                 5
# 30     30                 4

【讨论】:

  • 谢谢大卫 Jorquera。下面由 Lief Esbenshade 编写的最后一个示例代码完美地完成了我想要实现的目标!我认为我过多地考虑数学的复杂性,使自己过于复杂
  • 确实很好的答案!请记住接受为正确答案。
猜你喜欢
  • 2015-10-22
  • 2014-11-12
  • 2017-10-09
  • 2012-07-02
  • 1970-01-01
  • 2021-07-30
  • 2019-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多