2D numpy数组中元素的频率



我有一个形状为(1000,4)的numpy数组output。它是一个包含1000个没有重复的四元组的数组,并且它们是有序的(即元素是[0,1,2,3](。我想数一下我有多少次得到了所有可能的四胞胎。更实际地说,我使用以下代码:

comb=np.array(list(itertools.combinations(range(32),4)))
def counting(comb, output):
k=0
n_output=np.zeros(comb.shape[0])
for i in range(comb.shape[0]):
k=0
for j in range(output.shape[0]):
if (output[j]==comb[i]).all():
k+=1
n_output[i]=k
return n_output

如何优化代码?目前运行需要30秒

您当前的实现效率低下有两个原因:

  • 算法的复杂度为O(n^2)
  • 它使用(慢速CPython(循环

您使用Python集编写了一个简单的O(n)算法(仍然带有循环(,因为output没有任何重复。结果如下:

def countingFast(comb, output):
k=0
n_output=np.zeros(comb.shape[0])
tmp = set(map(tuple, output))
for i in range(comb.shape[0]):
n_output[i] = int(tuple(comb[i]) in tmp)
return n_output

在我的机器上,使用所描述的输入大小,原始版本需要55.2秒,而此实现需要0.038秒。这大约快了1400倍。

您可以生成一个布尔数组,表示要检查的序列是否等于数组中的给定行。由于numpy的布尔数组可以求和,因此可以使用此结果来获得匹配行的总数。

一个基本的方法可能是这样的(包括样本数据生成(:

import numpy as np
# set seed value of random generator to fixed value for repeatable output
np.random.seed(1234)
# create a random array with 950x4 elements
arr = np.random.rand(950, 4)
# create a 50x4 array with sample sequence
# this is the sequence we want to count in our final array
sequence = [0, 1, 2, 3]
sample = np.array([sequence, ]*50)
# stack arrays to create sample data with 1000x4 elements
arr = np.vstack((arr, sample))
# shuffle array to get a random distribution of random sample data and known sequence
np.random.shuffle(arr)
# check for equal array elements, returns a boolean array
results = np.equal(sequence, arr)
# sum the boolean array to get the number of total occurences per axis
# as the sum is the same for all columns, we just need to get the first element at index 0
occurences = np.sum(results, axis=0)[0]
print(occurences)
# --> 50

您需要为您感兴趣的每个序列调用所需的行。因此,编写这样的函数会很有用:

def number_of_occurences(data, sequence):
results = np.equal(sequence, data)
return np.sum(results, axis=0)[0]

最新更新