如何对数据进行分组,并限制 R 中的组大小

How to group data, with restrictions on group size in R

给定一个数据框,我可以将行分组到规定的 属性 下,对它们进行计数以了解组的大小,并为它们分配唯一的 ID 号。但我真正需要的是执行此过程,以便在以下三种情况下限制组大小:

  1. 如果 size modulo 3 = 0,则分成较小的组,所有的 size 都是 3,
  2. 如果尺寸模 3 = 1,则分成尺寸为 3 的较小组和尺寸为 2 的两组。
  3. 如果尺寸模 3 = 2,则分成尺寸为 3 的较小组和尺寸为 2 的一组

因此,如果大小为 4,则创建两个组,大小均为 2;而当尺寸为 5 时,则分成两组尺寸 3 和 2。

我创建了以下最小示例。

这是起始数据。通常,它不会被排序并且可以有更多的列:

   structure(
     list(property = c("A", "B", "B", "C", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "E", "F", "F", "F", "F", "F", "F", "G", "G", "G", "G", "G", "G", "G")), 
     class = c("tbl_df", "tbl", "data.frame"), 
     row.names = c(NA, -28L), 
     .Names = "property"
     )

所需的输出将是:

structure(
  list(property = c("A", "B", "B", "C", "C", "C", "D", "D", "D", "D", "E", "E", "E", "E", "E", "F", "F", "F", "F", "F", "F", "G", "G", "G", "G", "G", "G", "G"), 
  id = c(1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12)), 
  class = c("tbl_df", "tbl", "data.frame"), 
  row.names = c(NA, -28L), 
  .Names = c("property", "id")
  )

组的顺序并不重要。

我首先创建一个函数,它将根据您的要求创建相同数量的组。基本上,它总是会创建三个相等数字的组,然后在最后切断那些太多的数字。在特殊情况下,最后一组的长度为 1,最后一个元素被最后一个元素替换以满足您的条件 2:

create_grp_idx <- function(x) {
  n <- length(x)
  m <- n %/% 3 + 1
  idx <- rep(1:m, each = 3)[1:n]
  if (n %% 3 == 1 && n > 1) idx[n-1] <- idx[n]
  return (idx)
}

现在我使用 dplyrproperty 对数据进行分组,然后将 create_grp_idx() 应用于每个组,从而创建索引 n。然后,我使用 interaction()property 和新创建的索引 n 的每个组合中获取一个因子。由于您在示例中使用了数字,因此我将因子转换为数字,最后删除索引为 n.

的列
library(dplyr)
group_by(data, property) %>%
  mutate(n = create_grp_idx(property)) %>%
  ungroup %>%
  mutate(id = as.numeric(interaction(property, n))) %>%
  select(-n)
## Source: local data frame [28 x 2]
## 
##    property    id
##       (chr) (dbl)
## 1         A     1
## 2         B     2
## 3         B     2
## 4         C     3
## 5         C     3
## 6         C     3
## 7         D     4
## 8         D     4
## 9         D    11
## 10        D    11
## ..      ...   ...

这并没有完全给出您给出的示例输出,但是既然您说组的顺序无关紧要,我假设这就是您想要的结果。