web-dev-qa-db-ja.com

リストのnumpy配列を作成する方法は?

各要素がリストでなければならないnumpy配列を作成したいので、後で各要素に新しい要素を追加できます。

私はグーグルを見て、ここでスタックオーバーフローをすでに見ましたが、まだどこにも見つからないようです。

主な問題は、numpyがリストが配列になる必要があると想定していることですが、それは私が探しているものではありません。

23

あなたが発見したように、np.arrayは次のようなものが与えられたときに2D配列を作成しようとします

 A = np.array([[1,2],[3,4]],dtype=object)

このデフォルトの動作を回避するために、いくつかのトリックを適用しました。

1つは、サブリストの長さを可変にすることです。これらから2D配列を作成することはできないため、オブジェクト配列に頼ります。

In [43]: A=np.array([[1,2],[],[1,2,3,4]])
In [44]: A
Out[44]: array([[1, 2], [], [1, 2, 3, 4]], dtype=object)

そして、それらのリストのそれぞれに値を追加できます:

In [45]: for i in A: i.append(34)
In [46]: A
Out[46]: array([[1, 2, 34], [34], [1, 2, 3, 4, 34]], dtype=object)

np.emptyはオブジェクト配列も作成します:

In [47]: A=np.empty((3,),dtype=object)
In [48]: A
Out[48]: array([None, None, None], dtype=object)

ただし、要素をリストに変更する方法に注意する必要があります。 np.fillは魅​​力的ですが、問題があります:

In [49]: A.fill([])
In [50]: A
Out[50]: array([[], [], []], dtype=object)
In [51]: for i in A: i.append(34)
In [52]: A
Out[52]: array([[34, 34, 34], [34, 34, 34], [34, 34, 34]], dtype=object)

fillはすべてのスロットに同じリストを配置するため、1つを変更すると他のすべてのスロットが変更されます。リストのリストで同じ問題を得ることができます:

In [53]: B=[[]]*3
In [54]: B
Out[54]: [[], [], []]
In [55]: for i in B: i.append(34)
In [56]: B
Out[56]: [[34, 34, 34], [34, 34, 34], [34, 34, 34]]

emptyAを初期化する適切な方法は、反復を使用することです。

In [65]: A=np.empty((3,),dtype=object)
In [66]: for i,v in enumerate(A): A[i]=[v,i]
In [67]: A
Out[67]: array([[None, 0], [None, 1], [None, 2]], dtype=object)
In [68]: for v in A: v.append(34)
In [69]: A
Out[69]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34]], dtype=object)

リストに追加するのか、配列にリストを追加するのかは、質問とコメントから少し不明瞭です。リストへの追加を示しました。

np.append関数があり、これは新規ユーザーがよく誤用します。リストの追加に代わるものではありません。 np.concatenateのフロントエンドです。インプレース操作ではありません。新しい配列を返します。

また、追加するリストを定義するのは難しい場合があります。

In [72]: np.append(A,[[1,23]])
Out[72]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34], 1, 23],     dtype=object)

元のオブジェクトに連結するには、別のオブジェクト配列を作成する必要があります。

In [76]: np.append(A,np.empty((1,),dtype=object))
Out[76]: array([[None, 0, 34], [None, 1, 34], [None, 2, 34], None], dtype=object)

このすべてにおいて、リストの配列はリストのリストよりも構築が難しく、操作が簡単でも高速でもありません。いくつかの利点を引き出すには、リストの2次元配列にする必要があります。

In [78]: A[:,None]
Out[78]: 
array([[[None, 0, 34]],
       [[None, 1, 34]],
       [[None, 2, 34]]], dtype=object)

リストのリストのリストの作成と操作がより複雑になるため、オブジェクト配列を変形、転置などすることができます。

In [79]: A[:,None].tolist()
Out[79]: [[[None, 0, 34]], [[None, 1, 34]], [[None, 2, 34]]]

===

https://stackoverflow.com/a/57364472/901925 に示すように、np.frompyfuncはオブジェクトの配列を作成するための優れたツールです。

np.frompyfunc(list, 0, 1)(np.empty((3,2), dtype=object))  
27
hpaulj

リストの1次元配列が本当に必要な場合、numpyは常にリストを配列内の配列に変換しようとするため、独自のクラスでリストをラップする必要があります(より効率的ですが、明らかに一定のサイズの要素が必要です) 、たとえば

class mylist:

    def __init__(self, l):
        self.l=l

    def __repr__(self): 
        return repr(self.l)

    def append(self, x):
        self.l.append(x)

そして、他の要素の寸法を変更することなく、任意の要素を変更できます

>>> x = mylist([1,2,3])
>>> y = mylist([1,2,3])
>>> import numpy as np
>>> data = np.array([x,y])
>>> data
array([[1,2,3], [1,2,3]], dtype=object)
>>> data[0].append(2)
>>> data
array([[1,2,3,2], [1,2,3]], dtype=object)

更新

ALi_m実際には、numpyに強制的に参照用の1次元配列を作成してから、実際のリストをフィードする方法があります。

>>> data = np.empty(2, dtype=np.object)
>>> data[:] = [1, 2, 3], [1, 2, 3]
>>> data
array([[1, 2, 3], [1, 2, 3]], dtype=object)
>>> data[0].append(4)
>>> data
array([[1, 2, 3, 4], [1, 2, 3]], dtype=object)
7
lejlot