Python 不从给定列表中进行替换的重复采样

Python Repeated Sampling Without Replacement from a Given List

给定一个(例如)整数列表,我想在不替换的情况下对 n 个元素进行采样,从原始列表中删除采样的项目并重复此过程,直到现在原始列表中的元素仍然存在。返回 round(len(list)/n).

的列表

我知道 random.sample(),但是我没有找到无需替换的重复采样的实现。我下面的伪代码缺少从原始列表中删除采样元素的操作。但是,在我编写此功能时,我想知道是否已经实现了类似的功能或更优雅的解决方案?

伪代码

def repeated_sample_without_replacement(my_list, n):
    # where n = number of samples,
    k = int(len(my_list) / n)
    if len(my_list)%n != 0:
        samples = np.repeat(n,k)
        samples = np.append(samples, len(my_list) % n)
    else:
        samples = np.repeat(n,k)
    k = len(my_list) / n
    out = []
    for s in samples:
        out.append(random.sample(my_list, s))
        # remove the now sample elements from my_list
    
    return out

x = repeated_sample_without_replacement(ids,10)
print(x)

示例数据

# Sample Data
ids_clean = [*range(1,40)]
In[71]: # Remove Some ID to Better Represent my Purpose
ids = ids_clean[:12] + ids_clean[13:26] + ids_clean[27:]
ids
Out[73]: 
[1,
 2,
 3,
 4,
 5,
 6,
 7,
 8,
 9,
 10,
 11,
 12,
 14,
 15,
 16,
 17,
 18,
 19,
 20,
 21,
 22,
 23,
 24,
 25,
 26,
 28,
 29,
 30,
 31,
 32,
 33,
 34,
 35,
 36,
 37,
 38,
 39]
len(ids)
Out[74]: 37

期望输出

[[1,4,5,6..],[2,8,9,...],[13,15,16,...][27,10,..]]

您的代码表明您总体上是在尝试对整个给定列表进行抽样。所以只 random.shuffle 它一次,然后将它分成块。或者甚至只是用步骤 n 切片,这样更容易:

from random import shuffle

def repeated_sample_without_replacement(my_list, n):
    shuffle(my_list)
    return [my_list[i::n] for i in range(n)]

演示:

>>> repeated_sample_without_replacement(list(range(10)), 3)
[[7, 5, 0, 1], [2, 6, 8], [4, 3, 9]]

请注意,这实际上产生了 n 个样本。和你的不一样。

你的演示:

>>> repeated_sample_without_replacement(list(range(10)), 3)
[[3, 0, 2], [5, 4, 6], [6, 1, 7], [3]]
>>> repeated_sample_without_replacement(list(range(10)), 13)
[[1, 0, 3, 7, 8, 2, 5, 4, 9, 6]]