R:使用额外术语创建数据分区

R: Create Data Partition with extra term

我有以下 data.frame(比下面的例子更长)

sub height  group
1   1.55    a
2   1.65    a
3   1.76    b
4   1.77    a
5   1.58    c
6   1.65    d
7   1.82    c
8   1.91    c
9   1.77    b
10  1.69    b
11  1.74    a
12  1.75    c

我正在使用以下代码创建数据分区:

library("caret")
train = createDataPartition(df$group, p = 0.50)
partition = df[train, ]

所以它从每组中取一个概率为0.5的主题。 我的问题是在下面的例子中,有时会选择 d 组的主题,有时不会(因为 d 组真的很小)。我想创建一个约束,在我创建的每个分区中,将选择每个组中的 atlist 1 个主题。

任何优雅的解决方案?

我想出了一个不太优雅的解决方案,如下所示:

allGroupSamles <- c()
for (i in unique(df$groups))
{
  allGroupSamles <- c(allGroupSamles , sample(rownames(df[df$groups == i, ]) , 1, replace = TRUE))
}
allGroupSamles <- as.integer(allGroupSamles )

train = createDataPartition(df$groups, p = 0.50)[[1]]
train <- c(allGroupSamles , train)

partition= df[unique(train), ]

您可以在 data.frame 上使用 split 并在每组中抽取一半记录或 1 个记录,以较大者为准:

# apply a function over the split data.frame
samples <- lapply(split(df, df$group), function(x) {

  # the function takes a random sample of half the records in each group
  # by using `ceiling`, it guarantees at least one record
  s <- sample(nrow(x), ceiling(nrow(x)/2))
  x[s,]
})

train <- do.call(rbind, samples)

编辑:

如果你需要一个数值向量:

s <- tapply(1:nrow(df), df$group, function(x) {
  sample(x, ceiling(length(x)/2))
})

do.call(c, s)