Самый быстрый / правильный способ перебора массива NumPy - PullRequest
0 голосов
/ 24 января 2020

Какой самый быстрый способ перебора массива? Использование for l oop, как известно, медленнее, например:

>>> for element in the_array: do thing

Однако у меня есть массив размером (N, 7, 2), и мне нужно что-то сделать с каждым элементом N , Иногда это может быть векторизованное вычисление, поэтому я знаю, что там есть быстрое решение; иногда его запись в файл, хотя. Поэтому мое непосредственное решение состоит в том, чтобы перебрать Python range и проиндексировать массив:

>>> for i in range(N): file.write(str(list(map(list, the_array[i]))))

Существует ли более быстрый (или, возможно, правильный, если это неверный) способ перебора по массив

1 Ответ

0 голосов
/ 25 января 2020

Создайте образец

In [290]: arr = np.ones((1000,7,2),int) 

несколько простых итераций:

In [303]: timeit list(arr)                                                                       
247 µs ± 1.24 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [304]: timeit [row for row in arr]                                                            
287 µs ± 12.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [305]: timeit [arr[i] for i in range(arr.shape[0])]                                           
325 µs ± 1.65 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

полностью преобразуйте массив в список:

In [306]: timeit arr.tolist()                                                                    
657 µs ± 30.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [307]: timeit [row.tolist() for row in arr]                                                   
876 µs ± 3.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

уберите это преобразование из время и просто итерации в результирующем списке:

In [308]: %%timeit alist = arr.tolist() 
     ...: [row for row in alist]                                                                                        
36.9 µs ± 1.51 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Итерация в списке из 1000 элементов намного быстрее, чем итерация в первом измерении массива. Итерация массива должна создавать новый массив на каждом шаге, который является (относительно) медленным, даже если это view. Итерации списка просто должны ссылаться на элемент списка, который уже существует в памяти.

Теперь добавьте форматирование строки к задаче:

In [309]: timeit [str(row.tolist()) for row in arr]                                              
3.87 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)                                                                                        
In [310]: timeit [str(row) for row in arr.tolist()]                                              
3.77 ms ± 275 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [311]: timeit [str(arr[i].tolist()) for i in range(1000)]                                     
4.07 ms ± 62.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [312]: %%timeit alist = arr.tolist() 
     ...: [str(row) for row in alist]                                                                                        
3 ms ± 185 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Есть большой скачок во времени, к точке что он начинает затоплять различия итераций. Я ожидаю, что с записью файла поверх этого различия итераций почти исчезнут.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...