2017-11-06 16 views
1

3x4配列を生成しようとしていますが、各要素は未知のサイズの配列になります。処理中に、3x4マトリックスの特定のセルに新しい数値を1つずつ追加しています。私は最終的にはこのようになります配列で終わるしたい:2次元配列内に配列を追加/連結する

[[[1,8,9],[1,2],[],[]], 
[[8],[],[4,5],[9,1]], 
[[],[7,1,4],[],[2,1,3]]] 

は今、私は追加して連結を使用しようとしてきたが、私はので、これを行うには良い方法を見つけるように見えることはできません内側の配列はサイズが変化しています。また、私はマトリックスを初期化するのが最善の方法であるかどうかわかりません。私の行列に

mat = np.empty((3,4,1)) 
for x in range(1000): 
    i, j, value = somefunction() 
    mat[i,j,:] = np.append(mat[i,j,:], value) 

誰でも追加するための最良の方法を知っています(または連結またはを...)これらの値:簡体字、私のコードは次のようになりますか?私は追加と連結に関して同様の質問を探していて、いろいろなことを試みましたが、私はそれを理解することができませんでした。私は私の質問を説明することが非常に難しいと感じたので、私の説明がはっきりしていることを願っています。

+0

あなたはNumpyアレイでこれをしたいのですか?ナンシーアレイは一様であると考えられています。 IMHO、あなたはこのタスクのためにPythonリストを使用する必要があります。 –

+0

実際には配列を使うことは可能ですが、非常に非効率です。全体の質問は[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)のように聞こえます。この部分行列連結で何を達成しようとしていますか? – kazemakase

+0

実際、3x4配列はマップの一種であり、これらの値を正しい位置に格納して、各位置で多かれ少なかれ類似しているかどうかを確認したいのです。最後に、各セルで平均をとってみたいので、3×4の配列を残しておきます。 –

答えて

2

このジョブを実行するために、いわゆるオブジェクト配列を使用できます。通常、numpy配列はプリミティブ型で構成されますが、各要素が任意のPythonオブジェクトである配列を作成することは可能です。このようにして、配列を含む配列を作成できます。

mat = np.empty((3, 4), dtype=object) 

matの各要素が現在Noneであることに留意されたいです。これは仕事を得る必要があります

for x in range(1000): 
    i, j, value = somefunction() 
    if mat[i, j] is None: 
     mat[i, j] = np.array(value) 
    else: 
     mat[i, j] = np.append(mat[i, j], value) 

が、それは二つの理由で最も恐ろしく非効率的です::さんが行列を埋めてみましょう

  1. dtype=object numpyの配列は速く作る緩い、ほとんどすべてのプロパティ。ある要素に対するすべての操作は、通常は起こらないPythonインタプリタを必要とします。
  2. numpy配列は静的であるように設計されています。彼らは成長するように設計されていません。だからnp.appendが本当にしているのは、古い配列を新しい大きな配列にコピーすることです。これは、アレイが大きくなるにつれて、時間の経過とともに遅くなります。あなたが最終的には3×4配列の中に全部を減らしたいことを考えると、それは通常のPythonリストを操作するために、おそらく良いでしょう

# initialize a 3x4x0 hierarchy of nested lists 
mat = [[[] for _ in range(4)] for _ in range(3)] 

for x in range(1000): 
    i, j, value = somefunction() 
    mat[i][j].append(value) 

# reduce each sub-list to its mean (empty list -> nan) 
for i in range(3): 
    for j in range(4): 
     mat[i][j] = np.mean(mat[i][j]) 

# FINALLY convert to array 
mat = np.array(mat) 
1

ような配列がするかどうかをテストするための簡単な方法役立つことはnp.arrayにリストのリストをラップすることです:

In [767]: mat = np.array([[[1,8,9],[1,2],[],[]], 
    ...: [[8],[],[4,5],[9,1]], 
    ...: [[],[7,1,4],[],[2,1,3]]]) 
In [768]: mat 
Out[768]: 
array([[list([1, 8, 9]), list([1, 2]), list([]), list([])], 
     [list([8]), list([]), list([4, 5]), list([9, 1])], 
     [list([]), list([7, 1, 4]), list([]), list([2, 1, 3])]], dtype=object) 
In [769]: mat.shape 
Out[769]: (3, 4) 

結果は、(3,4)、オブジェクトDTYPE配列です。これは、オブジェクトdtype配列(np.empty((3,4),object)から始まるものがより一般的です)を作る最も信頼できる方法ではありませんが、この場合はうまくいきます。

しかし、このような配列は、元のリストのリストに比べて多くの利点を持っていません。より高速なアレイ操作のほとんどは機能しません。ほとんどのタスクでは、リスト要素に対してPythonレベルの反復処理が必要です。

私は手段を取るために、たとえば、反復するnp.vectorizeを使用することができます。

In [775]: np.vectorize(np.mean)(mat) 
/usr/local/lib/python3.5/dist-packages/numpy/core/fromnumeric.py:2909: RuntimeWarning: Mean of empty slice. 
    out=out, **kwargs) 
/usr/local/lib/python3.5/dist-packages/numpy/core/_methods.py:80: RuntimeWarning: invalid value encountered in double_scalars 
    ret = ret.dtype.type(ret/rcount) 
Out[775]: 
array([[ 6. , 1.5, nan, nan], 
     [ 8. , nan, 4.5, 5. ], 
     [ nan, 4. , nan, 2. ]]) 

それは空のリストの平均を取って好きではありません。[]をより適切に処理する簡単な関数を書くことができます。

私はアレイ(otypesの使用を注意してください)にリストを回すことができる:私はこれは非常に私たちを買うかわからないけれども

In [777]: arr = np.vectorize(np.array,otypes=[object])(mat) 
In [778]: arr 
Out[778]: 
array([[array([1, 8, 9]), array([1, 2]), array([], dtype=float64), 
     array([], dtype=float64)], 
     [array([8]), array([], dtype=float64), array([4, 5]), array([9, 1])], 
     [array([], dtype=float64), array([7, 1, 4]), 
     array([], dtype=float64), array([2, 1, 3])]], dtype=object)