このような場合、numpy でオブジェクト配列を使用しないでください。
それらは numpy 配列の基本的な目的を無効にし、ほんの一握りの状況で役立ちますが、ほとんどの場合、適切な選択ではありません。
はい、python で numpy 配列の個々の要素にアクセスするか、python で numpy 配列を反復処理すると、list
. y = [item * 2 for item in x]
(これが、 when x
is a numpy array のようなことを決してすべきではない理由です。)
Numpy オブジェクト配列は、リストよりもメモリ オーバーヘッドがわずかに低くなりますが、多数の個別の Python オブジェクトを保存している場合は、最初に他のメモリの問題が発生します。
Numpy は何よりもまず、均一な数値データ用のメモリ効率の高い多次元配列コンテナーです。numpy 配列に任意のオブジェクトを保持したい場合は、代わりにおそらくリストが必要です。
私のポイントは、numpy を効果的に使用したい場合は、構造化の方法を再考する必要があるかもしれないということです。
各オブジェクトインスタンスをnumpy配列に保存する代わりに、数値データをnumpy配列に保存し、行/列などごとに個別のオブジェクトが必要な場合は、各インスタンスのその配列にインデックスを保存します。
このようにして、数値配列をすばやく操作できます (つまり、リスト内包表記の代わりに numpy を使用します)。
私が話していることの簡単な例として、numpy を使用しない簡単な例を次に示します。
from random import random
class PointSet(object):
def __init__(self, numpoints):
self.points = [Point(random(), random()) for _ in xrange(numpoints)]
def update(self):
for point in self.points:
point.x += random() - 0.5
point.y += random() - 0.5
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
points = PointSet(100000)
point = points.points[10]
for _ in xrange(1000):
points.update()
print 'Position of one point out of 100000:', point.x, point.y
numpy 配列を使用した同様の例:
import numpy as np
class PointSet(object):
def __init__(self, numpoints):
self.coords = np.random.random((numpoints, 2))
self.points = [Point(i, self.coords) for i in xrange(numpoints)]
def update(self):
"""Update along a random walk."""
# The "+=" is crucial here... We have to update "coords" in-place, in
# this case.
self.coords += np.random.random(self.coords.shape) - 0.5
class Point(object):
def __init__(self, i, coords):
self.i = i
self.coords = coords
@property
def x(self):
return self.coords[self.i,0]
@property
def y(self):
return self.coords[self.i,1]
points = PointSet(100000)
point = points.points[10]
for _ in xrange(1000):
points.update()
print 'Position of one point out of 100000:', point.x, point.y
これを行う方法は他にもあります (たとえば、特定のnumpy 配列への参照を each に保存したくない場合がありますpoint
) が、これが役立つ例であることを願っています。
走る速さの違いに注目。私のマシンでは、numpy バージョンでは 5 秒、pure-python バージョンでは 60 秒の差があります。