[英]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.