[python] 생성기에서 numpy 배열을 어떻게 작성합니까?

생성기 객체에서 numpy 배열을 어떻게 만들 수 있습니까?

문제를 설명해 드리겠습니다.

>>> 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])

이 경우 gimme()출력을 배열로 바꾸고 싶은 발전기입니다. 그러나 배열 생성자는 생성기를 반복하지 않고 단순히 생성기 자체를 저장합니다. 내가 원하는 동작은 from numpy.array(list(gimme()))이지만, 중간 목록과 최종 배열을 메모리에 동시에 갖는 메모리 오버 헤드를 지불하고 싶지 않습니다. 더 공간 효율적인 방법이 있습니까?



답변

Numpy 배열은 파이썬 목록과 달리 작성 시간에 명시 적으로 길이를 설정해야합니다. 각 항목의 공간을 메모리에 연속적으로 할당 할 수 있도록하기 위해 필요합니다. 연속 할당은 numpy 배열의 주요 기능입니다. 네이티브 코드 구현과 결합하면 일반 목록보다 훨씬 빠르게 작업을 실행할 수 있습니다.

이를 염두에두고 다음 중 하나가 아니면 발전기 객체를 가져 와서 배열로 만드는 것은 기술적으로 불가능합니다.

  1. 실행할 때 얼마나 많은 요소가 생성되는지 예측할 수 있습니다.

    my_array = numpy.empty(predict_length())
    for i, el in enumerate(gimme()): my_array[i] = el
  2. 중간 목록에 요소를 기꺼이 저장합니다.

    my_array = numpy.array(list(gimme()))
  3. 두 개의 동일한 생성기를 만들고 첫 번째 생성기를 통해 전체 길이를 찾은 다음 배열을 초기화 한 다음 생성기를 다시 실행하여 각 요소를 찾을 수 있습니다.

    length = sum(1 for el in gimme())
    my_array = numpy.empty(length)
    for i, el in enumerate(gimme()): my_array[i] = el

1 은 아마도 당신이 찾고있는 것입니다. 2 는 공간이 비효율적이며 3 은 시간이 비효율적입니다 (발전기를 두 번 통과해야 함).


답변

이 stackoverflow 결과 뒤에 하나의 Google이 있습니다 numpy.fromiter(data, dtype, count). 디폴트 count=-1는 iterable에서 모든 요소를 ​​가져옵니다. a dtype를 명시 적으로 설정 해야합니다 . 제 경우에는 다음과 같이 작동했습니다.

numpy.fromiter(something.generate(from_this_input), float)


답변

을 사용하여 생성기에서 1D 배열을 생성 할 수 있지만 다음을 사용하여 생성기 numpy.fromiter()에서 ND 배열을 생성 할 수 있습니다 numpy.stack.

>>> mygen = (np.ones((5, 3)) for _ in range(10))
>>> x = numpy.stack(mygen)
>>> x.shape
(10, 5, 3)

1D 배열에서도 작동합니다.

>>> numpy.stack(2*i for i in range(10))
array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

참고 numpy.stack내부적으로 발전기를 소비하고와 중간 목록을 작성한다 arrays = [asanyarray(arr) for arr in arrays]. 구현은 여기 에서 찾을 수 있습니다 .


답변

다소 접선이지만 생성기가 목록 이해력 인 경우 numpy.where결과를보다 효과적으로 얻는 데 사용할 수 있습니다 (이 게시물을 본 후 내 코드에서 이것을 발견했습니다)


답변

vstack , hstackdstack의 기능은 다차원 어레이를 생성 입력 발전기로서 취할 수있다.


답변