1. ホーム
  2. python

[解決済み] リストのnumpy配列を作成する方法は?

2022-03-02 09:41:18

質問

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

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

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

どのように解決するのですか?

お分かりのように np.array のようなものが与えられると、2次元の配列を作ろうとします。

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

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

ひとつは、サブリストの長さを可変にすることです。 これでは2次元の配列を作ることができないので、オブジェクトの配列に頼ることになります。

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

を初期化するのが正しい方法です。 empty A はイテレーションで、例えば

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