Jak zbudować tablicę numpy z generatora?
Jak mogę zbudować tablicę numpy z obiektu generatora?
Pozwól mi zilustrować problem:
>>> import numpy
>>> def gimme():
... for x in xrange(10):
... yield x
...
>>> gimme()
<generator object at 0x28a1758>
>>> list(gimme())
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> numpy.array(xrange(10))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> numpy.array(gimme())
array(<generator object at 0x28a1758>, dtype=object)
>>> numpy.array(list(gimme()))
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
W tym przypadku, gimme()
jest generatorem, którego wyjście chciałbym przekształcić w tablicę. Jednak konstruktor tablicy nie iteruje nad generatorem, tylko przechowuje sam generator. Zachowanie, którego pragnę, jest takie, że z numpy.array(list(gimme()))
, ale nie chcę płacić narzutu pamięci z posiadania listy pośredniej i końcowej tablicy w pamięci w tym samym czas. Czy istnieje bardziej oszczędny sposób?
5 answers
Tablice Numpy wymagają, aby ich długość była ustawiana jawnie podczas tworzenia, w przeciwieństwie do list Pythona. Jest to konieczne, aby przestrzeń dla każdego elementu mogła być kolejno przydzielana w pamięci. Sekwencyjna alokacja jest kluczową cechą tablic numpy: w połączeniu z implementacją kodu natywnego operacje na nich wykonywane są znacznie szybciej niż zwykłe listy.
Mając to na uwadze, technicznie niemożliwe jest wzięcie obiektu generatora i przekształcenie go w tablicę, chyba że albo:
-
Potrafi przewidzieć ile elementów wyda się po uruchomieniu:
my_array = numpy.empty(predict_length()) for i, el in enumerate(gimme()): my_array[i] = el
-
Są chętni do przechowywania jego elementów na liście pośredniej:
my_array = numpy.array(list(gimme()))
-
Może utworzyć dwa identyczne Generatory, uruchomić pierwszy, aby znaleźć całkowitą długość, zainicjalizować tablicę, a następnie ponownie uruchomić generator, aby znaleźć każdy element:
length = sum(1 for el in gimme()) my_array = numpy.empty(length) for i, el in enumerate(gimme()): my_array[i] = el
1 pewnie tego szukasz. 2 jest przestrzeń nieefektywna, a 3 jest czas nieefektywny(trzeba przejść przez generator dwa razy).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-17 13:31:01
Jeden google za tym wynikiem stackoverflow, stwierdziłem, że jest numpy.fromiter(data, dtype, count)
. Domyślna count=-1
pobiera wszystkie elementy z iterable. Wymaga jawnego Ustawienia dtype
. W moim przypadku to zadziałało:
numpy.fromiter(something.generate(from_this_input), float)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-21 21:09:08
Podczas gdy możesz utworzyć tablicę 1D z generatora za pomocą numpy.fromiter()
, możesz utworzyć tablicę N-D z generatora za pomocą numpy.stack
:
>>> mygen = (np.ones((5, 3)) for _ in range(10))
>>> x = numpy.stack(mygen)
>>> x.shape
(10, 5, 3)
Działa również dla tablic 1D:
>>> numpy.stack(2*i for i in range(10))
array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
Zauważ, że {[3] } wewnętrznie zużywa generator i tworzy listę pośrednią z arrays = [asanyarray(arr) for arr in arrays]
. Implementację można znaleźć tutaj .
[WARNING] Jak zauważył @Joseh Seedy, Numpy 1.16 wyświetla ostrzeżenie, które pokonuje użycie takiej funkcji z generatorami.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-07 02:50:36
Nieco styczny, ale jeśli twój generator jest rozumieniem listy, możesz użyć numpy.where
, aby skuteczniej uzyskać wynik (odkryłem to we własnym kodzie po obejrzeniu tego postu)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 18:38:55
The vstack, Funkcje hstack i dstack mogą przyjmować jako generatory wejściowe generujące wielowymiarowe tablice.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-14 20:27:17