各要素がリストでなければならないnumpy配列を作成したいので、後で各要素に新しい要素を追加できます。
私はグーグルを見て、ここでスタックオーバーフローをすでに見ましたが、まだどこにも見つからないようです。
主な問題は、numpyがリストが配列になる必要があると想定していることですが、それは私が探しているものではありません。
あなたが発見したように、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]]
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))
リストの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)