Согласование np.fromiter и многомерных массивов в Python

Мне нравится использовать np.fromiter из numpy, потому что это ресурсоемкий способ создания np.array объектов. Однако похоже, что он не поддерживает многомерные массивы, которые тоже весьма полезны.

import numpy as np

def fun(i):
    """ A function returning 4 values of the same type.
    """
    return tuple(4*i + j for j in range(4))

# Trying to create a 2-dimensional array from it:
a = np.fromiter((fun(i) for i in range(5)), '4i', 5) # fails

# This function only seems to work for 1D array, trying then:
a = np.fromiter((fun(i) for i in range(5)),
        [('', 'i'), ('', 'i'), ('', 'i'), ('', 'i')], 5) # painful

# .. `a` now looks like a 2D array but it is not:
a.transpose() # doesn't work as expected
a[0, 1] # too many indices (of course)
a[:, 1] # don't even think about it

Как я могу сделать a многомерным массивом, сохранив при этом такую ​​ленивую конструкцию на основе генераторов?


person iago-lito    schedule 01.12.2015    source источник


Ответы (1)


Сам по себе np.fromiter поддерживает только построение одномерных массивов, и поэтому он ожидает, что итерация будет давать отдельные значения, а не кортежи / списки / последовательности и т. д. Один из способов обойти это ограничение - использовать _ 2_, чтобы лениво" распаковать "вывод выражения генератора в одну одномерную последовательность значений:

import numpy as np
from itertools import chain

def fun(i):
    return tuple(4*i + j for j in range(4))

a = np.fromiter(chain.from_iterable(fun(i) for i in range(5)), 'i', 5 * 4)
a.shape = 5, 4

print(repr(a))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19]], dtype=int32)
person ali_m    schedule 01.12.2015