【发布时间】:2018-05-03 16:49:18
【问题描述】:
我正在尝试编写一个模拟,其中涉及将项目随机重新分配到具有一些限制的类别。
假设我有一组 1 到 N 的鹅卵石分布在桶 A 到 J:
set.seed(100)
df1 <- data.frame(pebble = 1:100,
bucket = sample(LETTERS[1:10], 100, T),
stringsAsFactors = F)
head(df1)
#> pebble bucket
#> 1 1 D
#> 2 2 C
#> 3 3 F
#> 4 4 A
#> 5 5 E
#> 6 6 E
我想将鹅卵石随机重新分配给桶。没有限制,我可以这样做:
random.permutation.df1 <- data.frame(pebble = df1$pebble, bucket = sample(df1$bucket))
colSums(table(random.permutation.df1))
#> A B C D E F G H I J
#> 4 7 13 14 12 11 11 10 9 9
colSums(table(df1))
#> A B C D E F G H I J
#> 4 7 13 14 12 11 11 10 9 9
重要的是,这会重新分配鹅卵石,同时确保每个桶保留相同的数字(因为我们是在没有替换的情况下进行抽样)。
但是,我有一组限制,例如某些鹅卵石不能分配给某些桶。我在df2 中编码了限制:
df2 <- data.frame(pebble = sample(1:100, 10),
bucket = sample(LETTERS[1:10], 10, T),
stringsAsFactors = F)
df2
#> pebble bucket
#> 1 33 I
#> 2 39 I
#> 3 5 A
#> 4 36 C
#> 5 55 J
#> 6 66 A
#> 7 92 J
#> 8 95 H
#> 9 2 C
#> 10 49 I
这里的逻辑是 33 号和 39 号鹅卵石不能放在 I 桶中,5 号鹅卵石不能放在 A 桶中,等等。我想根据这些限制置换哪些鹅卵石在哪个桶中。
到目前为止,我已经考虑过如下循环处理它,但这不会导致桶保留相同数量的鹅卵石:
perms <- character(0)
cnt <- 1
for (p in df1$pebble) {
perms[cnt] <- sample(df1$bucket[!df1$bucket %in% df2$bucket[df2$pebble==p]], 1)
cnt <- cnt + 1
}
table(perms)
#> perms
#> A B C D E F G H I J
#> 6 7 12 22 15 1 14 7 7 9
然后我尝试采样位置,然后从可用存储桶和可用剩余位置中删除该位置。这也不起作用,我怀疑这是因为我正在对树的分支进行采样,但不会产生解决方案。
set.seed(42)
perms <- character(0)
cnt <- 1
ids <- 1:nrow(df1)
bckts <- df1$bucket
for (p in df1$pebble) {
id <- sample(ids[!bckts %in% df2$bucket[df2$pebble==p]], 1)
perms[cnt] <- bckts[id]
bckts <- bckts[-id]
ids <- ids[ids!=id]
cnt <- cnt + 1
}
table(perms)
#> perms
#> A B C D E F G J
#> 1 1 4 1 2 1 2 2
非常感谢任何想法或建议(并为篇幅道歉)。
编辑:
我愚蠢地忘记澄清我之前只是通过重新采样来解决这个问题,直到我得到一个不违反df2 中任何条件的平局,但我现在有很多条件,这会使我的代码占用运行时间太长。如果我能找到一种方法让强制它更快,我仍然愿意尝试强制它。
【问题讨论】:
-
你有多少限制?你能不能
while循环整个重新采样并检查是否满足限制并打破它? -
@rawr 这实际上是我之前所做的(应该提到抱歉)但我现在有更多限制,所以以前需要几个小时才能运行的代码现在看起来可能需要更长的时间。我仍然愿意尝试以某种方式暴力破解它,但纯粹的
while(cond) sample(df1$bucket)现在太慢了。