¿Cuenta de manera eficiente la cantidad de ocurrencias de subarreglos únicos en NumPy?

Tengo una serie de formas (128, 36, 8) y me gustaría encontrar el número de ocurrencias de los subarreglos únicos de longitud 8 en la última dimensión.

Soy consciente de np.unique y np.bincount , pero parecen ser elementos en lugar de subarrays. He visto esta pregunta pero se trata de encontrar la primera aparición de un subarreglo en particular, en lugar de los conteos de todos los subarreglos únicos.

La pregunta establece que la matriz de entrada es de forma (128, 36, 8) y estamos interesados ​​en encontrar subarreglos únicos de longitud 8 en la última dimensión. Por lo tanto, asumo que la unicidad está en las dos primeras dimensiones que se fusionan. Asummos A como la matriz de entrada 3D.

Consigue el número de subarreglos únicos

 # Reshape the 3D array to a 2D array merging the first two dimensions Ar = A.reshape(-1,A.shape[2]) # Perform lex sort and get the sorted indices and xy pairs sorted_idx = np.lexsort(Ar.T) sorted_Ar = Ar[sorted_idx,:] # Get the count of rows that have at least one TRUE value # indicating presence of unique subarray there unq_out = np.any(np.diff(sorted_Ar,axis=0),1).sum()+1 

Ejecución de la muestra

 In [159]: A # A is (2,2,3) Out[159]: array([[[0, 0, 0], [0, 0, 2]], [[0, 0, 2], [2, 0, 1]]]) In [160]: unq_out Out[160]: 3 

Obtenga el recuento de ocurrencias de subarrays únicos

 # Reshape the 3D array to a 2D array merging the first two dimensions Ar = A.reshape(-1,A.shape[2]) # Perform lex sort and get the sorted indices and xy pairs sorted_idx = np.lexsort(Ar.T) sorted_Ar = Ar[sorted_idx,:] # Get IDs for each element based on their uniqueness id = np.append([0],np.any(np.diff(sorted_Ar,axis=0),1).cumsum()) # Get counts for each ID as the final output unq_count = np.bincount(id) 

Ejecución de la muestra

 In [64]: A Out[64]: array([[[0, 0, 2], [1, 1, 1]], [[1, 1, 1], [1, 2, 0]]]) In [65]: unq_count Out[65]: array([1, 2, 1], dtype=int64) 

Aquí he modificado la muy útil respuesta de @Divakar para devolver los conteos de los subconjuntos únicos, así como los propios subconjuntos, de modo que la salida sea la misma que la de collections.Counter.most_common() :

 # Get the array in 2D form. arr = arr.reshape(-1, arr.shape[-1]) # Lexicographically sort sorted_arr = arr[np.lexsort(arr.T), :] # Get the indices where a new row appears diff_idx = np.where(np.any(np.diff(sorted_arr, axis=0), 1))[0] # Get the unique rows unique_rows = [sorted_arr[i] for i in diff_idx] + [sorted_arr[-1]] # Get the number of occurences of each unique array (the -1 is needed at # the beginning, rather than 0, because of fencepost concerns) counts = np.diff( np.append(np.insert(diff_idx, 0, -1), sorted_arr.shape[0] - 1)) # Return the (row, count) pairs sorted by count return sorted(zip(unique_rows, counts), key=lambda x: x[1], reverse=True) 

No estoy seguro de que sea la forma más eficiente de hacerlo, pero debería funcionar.

 arr = arr.reshape(128*36,8) unique_ = [] occurence_ = [] for sub in arr: if sub.tolist() not in unique_: unique_.append(sub.tolist()) occurence_.append(1) else: occurence_[unique_.index(sub.tolist())]+=1 for index_,u in unique_: print u,"occurrence: %s"%occurence_[index_]