如何在保持数据分布的同时从python中的列表中随机抽样

时间:2017-04-03 19:40:07

标签: python random distribution frequency-distribution

基本上我要做的是从列表中随机选择项目,同时保持内部分布。请参阅以下示例。

a = 17%
b = 12%
c = 4%
etc.

“a”在列表中有1700个项目。 “b”在列表中有1200个项目。 “c”在列表中有400个项目。

我想要一个模仿a,b,c等分布的样本,而不是使用所有信息。

所以目标是结束,

从“a”中随机选择170个项目 120个随机选择的项目来自“b” 从“c”中随机选择40个项目

我知道如何从列表中随机选择信息,但我无法弄清楚如何在强制结果具有相同分布时随机选择。

5 个答案:

答案 0 :(得分:4)

如果您的列表不是很大且内存不是问题,您可以使用这种简单的方法。

要从nab获取c个元素,您可以将这三个列表连接在一起,并使用{{3}从结果列表中选择随机元素}:

import random

n = 50
a = ['a'] * 170
b = ['b'] * 120
c = ['c'] * 40
big_list = a + b + c
random_elements = [random.choice(big_list) for i in range(n)]
# ['a', 'c', 'a', 'a', 'a', 'b', 'a', 'c', 'b', 'a', 'c', 'a',
# 'a', 'a', 'a', 'b', 'b', 'a', 'a', 'a', 'a', 'a', 'c', 'a',
# 'c', 'a', 'b', 'a', 'a', 'c', 'a', 'b', 'a', 'c', 'b', 'a',
# 'a', 'b', 'a', 'b', 'a', 'a', 'c', 'a', 'c', 'a', 'b', 'c',
# 'b', 'b']

对于每个元素,从len(a) / len(a + b + c)获取元素的概率为a

您可能会多次获得相同的元素。如果您不希望发生这种情况,可以使用random.choice

答案 1 :(得分:0)

根据我的理解,您有三个不同的群体,您想要随机抽取这些群体,但是选择某些群体的概率存在偏差。在这种情况下,首先生成对应于每个群体的索引列表更容易(因为我将它们组合成称为combined的单个2D阵列)。

然后,您可以遍历随机生成的索引列表,这将为您提供您可以选择的人口,然后使用np.random.choice()从该数据中随机选择。

import numpy as np

sample_a = np.arange(1, 1000)
sample_b = np.arange(1001, 2000)
sample_c = np.arange(2001, 3000)

combined = np.vstack((sample_a, sample_b, sample_c))

distributions = [0.7, 0.2, 0.1] # The skewed probability distribution for sampling

sample = np.random.choice([0, 1, 2], size=10, p=distributions) # Choose indices with skewed probability

combined_pool = []

for arr in sample:
    combined_pool.append(np.random.choice(combined[arr]))

答案 2 :(得分:0)

在您的选择中“模仿”此类分布的一种方法是简单地将列表合并为一个,然后从该列表中选择所需的总项目数。如果需要选择的项目总数很大,那么这个近似值就会很好。

请注意,它并不能保证将精确选择每个列表中的数量。但是,如果列表很大并且此例程有很多次运行,则平均值应该很好。

import random
 total = a + b + c + ...
 samples = []
 number = len(total) / 10
 for i in range(number):
     samples.append(total[random.rand(0, len(total) - 1])

答案 3 :(得分:0)

手动执行此操作非常简单。让我们将您的数据存储在(value, probability)个对象列表中:

data = [(a, 0.17), (b, 0.12), (c, 0.04), ...]

这个函数可以帮助您选择遵循概率分布的随机值:

import random
def select_random_element(data):
    sample_proba = random.uniform(0, 1)
    total_proba = 0
    for (value, proba) in data:
        total_proba += proba
        if total_proba >= sample_proba:
            return value

最后,这是我们选择N个随机项目的方式:

random_items = [select_random_element(data) for _ in range(0, N)]

这不需要任何额外的内存。但是,时间复杂度为O(len(data)*N)。这可以通过事先降低概率对数据列表进行排序来改进:

data = sorted(data, key=lambda i: i[1], reverse=True)

请注意,我假设您的数据的总概率为1.如果不是,您应该在上面的代码中写random.uniform(0, total_probability)而不是random.uniform(0, 1),其中包含:

total_probability = sum([i[1] for i in data])

答案 4 :(得分:-1)

只需在列表中使用shuffle,然后取前n个元素。