簡體   English   中英

計算numpy.array中每行的出現次數

[英]Count how many times each row is present in numpy.array

我試圖計算np.array每行顯示的np.array ,例如:

import numpy as np
my_array = np.array([[1, 2, 0, 1, 1, 1],
                     [1, 2, 0, 1, 1, 1], # duplicate of row 0
                     [9, 7, 5, 3, 2, 1],
                     [1, 1, 1, 0, 0, 0], 
                     [1, 2, 0, 1, 1, 1], # duplicate of row 0
                     [1, 1, 1, 1, 1, 0]])

[1, 2, 0, 1, 1, 1] 1,2,0,1,1,1 [1, 2, 0, 1, 1, 1]顯示3次。

一個簡單的天真解決方案將涉及將我的所有行轉換為元組,並應用collections.Counter ,如下所示:

from collections import Counter
def row_counter(my_array):
    list_of_tups = [tuple(ele) for ele in my_array]
    return Counter(list_of_tups)

產量:

In [2]: row_counter(my_array)
Out[2]: Counter({(1, 2, 0, 1, 1, 1): 3, (1, 1, 1, 1, 1, 0): 1, (9, 7, 5, 3, 2, 1): 1, (1, 1, 1, 0, 0, 0): 1})

但是,我擔心我的方法的效率。 也許有一個庫提供了這樣做的內置方式。 我把這個問題標記為pandas因為我認為pandas可能有我正在尋找的工具。

您可以使用您的其他問題的答案來獲取唯一項目的計數。

在numpy 1.9中有一個return_counts可選的關鍵字參數,所以你可以簡單地做:

>>> my_array
array([[1, 2, 0, 1, 1, 1],
       [1, 2, 0, 1, 1, 1],
       [9, 7, 5, 3, 2, 1],
       [1, 1, 1, 0, 0, 0],
       [1, 2, 0, 1, 1, 1],
       [1, 1, 1, 1, 1, 0]])
>>> dt = np.dtype((np.void, my_array.dtype.itemsize * my_array.shape[1]))
>>> b = np.ascontiguousarray(my_array).view(dt)
>>> unq, cnt = np.unique(b, return_counts=True)
>>> unq = unq.view(my_array.dtype).reshape(-1, my_array.shape[1])
>>> unq
array([[1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0],
       [1, 2, 0, 1, 1, 1],
       [9, 7, 5, 3, 2, 1]])
>>> cnt
array([1, 1, 3, 1])

在早期版本中,您可以這樣做:

>>> unq, _ = np.unique(b, return_inverse=True)
>>> cnt = np.bincount(_)
>>> unq = unq.view(my_array.dtype).reshape(-1, my_array.shape[1])
>>> unq
array([[1, 1, 1, 0, 0, 0],
       [1, 1, 1, 1, 1, 0],
       [1, 2, 0, 1, 1, 1],
       [9, 7, 5, 3, 2, 1]])
>>> cnt
array([1, 1, 3, 1])

(這假設數組相當小,例如少於1000行。)

這是一個簡短的NumPy方法來計算每行在數組中出現的次數:

>>> (my_array[:, np.newaxis] == my_array).all(axis=2).sum(axis=1)
array([3, 3, 1, 1, 3, 1])

這會計算每行在my_array出現的次數,返回一個數組,其中第一個值顯示第一行出現的次數,第二個值顯示第二行出現的次數,依此類推。

您的解決方案也不錯,但如果您的矩陣很大,您可能希望在計數之前使用更高效的哈希(與計數器使用的默認值相比)。 你可以用joblib做到這一點

A = np.random.rand(5, 10000)

%timeit (A[:,np.newaxis,:] == A).all(axis=2).sum(axis=1)
10000 loops, best of 3: 132 µs per loop

%timeit Counter(joblib.hash(row) for row in A).values()
1000 loops, best of 3: 1.37 ms per loop

%timeit Counter(tuple(ele) for ele in A).values()
100 loops, best of 3: 3.75 ms per loop

%timeit pd.DataFrame(A).groupby(range(A.shape[1])).size()
1 loops, best of 3: 2.24 s per loop

使用這么多列,大熊貓解決方案非常慢(每個循環大約2秒)。 對於像你所展示的小矩陣,你的方法比joblib散列更快但比numpy慢:

numpy: 100000 loops, best of 3: 15.1 µs per loop
joblib:1000 loops, best of 3: 885 µs per loop
tuple: 10000 loops, best of 3: 27 µs per loop
pandas: 100 loops, best of 3: 2.2 ms per loop

如果你有大量的行,那么你可以找到一個更好的替代計數器來查找哈希頻率。

編輯 :在我的系統中添加來自@ acjr解決方案的numpy基准測試,以便更容易比較。 在兩種情況下,numpy解決方案是最快的解決方案。

大熊貓的方法可能看起來像這樣

import pandas as pd

df = pd.DataFrame(my_array,columns=['c1','c2','c3','c4','c5','c6'])
df.groupby(['c1','c2','c3','c4','c5','c6']).size()

注意:不需要提供列名

我認為只需在np.unique指定axis np.unique您的需求。

import numpy as np
unq, cnt = np.unique(my_array, axis=0, return_counts=True)

注意:此功能僅在numpy>=1.13.0

可以在numpy_indexed包中找到與Jaime相同的解決方案(免責聲明:我是其作者)

import numpy_indexed as npi
npi.count(my_array)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM