Из-за размера ваших матриц и требований вашей проблемы, я думаю, итерация неизбежна.Вы не можете использовать широковещательную рассылку, так как она взорвет вашу память, поэтому вам нужно работать с существующим массивом построчно.Однако вы можете использовать numba
и njit
, чтобы значительно ускорить этот процесс по сравнению с подходом чистого Python.
import numpy as np
from numba import njit
@njit
def zero_out_contained_rows(a):
"""
Finds rows where all of the elements are
equal or smaller than all corresponding
elements of anothe row, and sets all
values in the row to zero
Parameters
----------
a: ndarray
The array to modify
Returns
-------
The modified array
Examples
--------
>>> zero_out_contained_rows(np.array([[1, 0, 1], [0, 1, 0], [1, 0, 0]]))
array([[1, 0, 1],
[0, 1, 0],
[0, 0, 0]])
"""
x, y = a.shape
contained = np.zeros(x, dtype=np.bool_)
for i in range(x):
for j in range(x):
if i != j and not contained[j]:
equal = True
for k in range(y):
if a[i, k] < a[j, k]:
equal = False
break
contained[j] = equal
a[contained] = 0
return a
Это позволяет отслеживать, используется ли строка в другомстрока.Это предотвращает множество ненужных сравнений путем короткого замыкания, прежде чем окончательно уничтожить строки, содержащиеся в других, с помощью 0
.
По сравнению с вашей первоначальной попыткой использования итерации, это также улучшение скоростиas также обрабатывает обнуление правильных строк.
a = np.random.randint(0, 2, (6000, 6000))
%timeit zero_out_contained_rows(a)
1.19 s ± 1.87 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Я обновлю время, как только ваша попытка завершится (в настоящее время ~ 10 минут).