python - 从列表列表中统一抽取5个元素

标签 python random

这有一些背景,所以请耐心等待。

我有一个列表列表,称之为 nested_lists,其中每个列表的形式为 [[1,2,3,...], [4,3,1,.. .]](即每个列表包含两个整数列表)。现在,在这些列表中的每一个中,两个整数列表具有相同的长度,并且对应于相同索引的两个整数表示 R^2 中的坐标。 因此,例如,(1,4) 将是上述示例中的一个坐标。

现在,我的任务是从 nested_lists 中统一抽取 5 个唯一坐标(即每个坐标被选中的概率相同),无需替换。也就是说,从 nested_lists 中的列表中的所有坐标,我试图统一绘制 5 个唯一坐标而无需替换。

一个非常直接的方法是: 1. 在 nested_lists 中创建一个包含所有唯一坐标的列表。 2、使用numpy.random.choice对5个元素进行统一采样,不放回。 代码将是这样的:

import numpy as np
coordinates = []
#Get list of all unique coordinates
for list in nested_lists:
    
    l = len(list[0])
    for i in range(0, l):
        
        coordinate = (list[0][i], list[1][i])
        if coordinate not coordinates:
            coordinates += [coordinate]

draws = np.random.choice(coordinates, 5, replace=False, p= [1/len(coordinates)]*len(coordinates))

但是获取所有唯一坐标的集合在计算上可能非常昂贵,特别是如果 nested_lists 包含数百万个列表,每个列表中都有数千个坐标。因此,我正在寻找无需先获取所有坐标列表即可执行相同绘制的方法。

我想到的一种方法是从 nested_lists 中的每个列表中使用加权概率进行采样。 所以得到每个列表的大小(坐标个数)的列表,然后遍历每个列表,以概率绘制坐标 (size/sum(size))*(1/sum(sizes))。重复这个过程,直到绘制出 5 个唯一的坐标,然后应该对应于我们想要绘制的内容。代码将是这样的:

no_coordinates = lambda x: len(x[0])
sizes = list(map(no_coordinates, nested_lists))
i = 0
sum_sizes = sum(sizes)
draws = []
while i != 5:                           #to make sure we get 5 draws

    for list in nested_lists:
      
        size = len(list[0])
        p = size/(sum_sizes**2)
        for j in range(0, size):
            
            if i >= 5:                        exit for loop when we reach 5 draws
                break
            if np.random.random() < p and (list[0][j], list[1][j]) not in draws:
                draws += (list[0][j], list[1][j])
                i += 1
            
            

上面的代码似乎在计算上更有效率,但我不确定它是否真的以与整体所需的相同概率绘制。根据我的计算,总体概率将 sum(size)/sum_sizes**21/sum_sizes(我们所需的概率)相同,但我还是我不确定这是否正确。

所以我想知道是否有更有效的方法来绘制我想要的,我的方法是否正确。

最佳答案

您可以使用 bootstrapping .基本上,这个想法是通过替换绘制一些大量(但固定)的坐标来估计每个坐标的概率。然后,您可以使用转换后的密度从此列表中进行子采样。

from collections import Counter

bootstrap_sample_size = 1000
total_lists = len(nested_lists)
list_len = len(nested_lists[0])
# set will make more sense in this example
# I used counter to allow for future statistical manipulations
c = Counter()

for _ in range(bootstrap_sample_size):
    x, y = random.randrange(total_lists), random.randrange(list_len) 
    random_point = nested_lists[x][0][y], nested_lists[x][1][y]
    c.update((random_point,))

# now c contains counts for 1000 points with replacements
# let's just ignore these probabilities to get uniform sample
result = random.sample(c.keys(), 5)

这不会是完全均匀的,但是 bootstrap 提供了统计保证,随着 bootstrap_sample_size 的增加,它将任意接近均匀分布。 1000 个样本通常足以满足大多数现实生活中的应用。

关于python - 从列表列表中统一抽取5个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62796835/

相关文章:

python - pyqt中使用lambda表达式连接槽

python - 如何随机化画板中显示的图像

python - 如何从所有 pandas 列计算成对矩阵

python - 在 Flask App 中,Celery 应该在哪里实例化?

java - Kolmogorov-Smirnov 2 样本测试 Java 给出 0 p 值

python - 如何从 Tensorflow 中的字符串张量中随机删除空格

c# - 使用静态方法生成随机数是一种好习惯吗?

python - 我可以对 UUID 进行哈希处理以获得更高的熵 - Python

python - 在 Linux 中创建两个进程并获取输出

具有许多属性的python类