2016-09-15 22 views
1

NumPy配列をネイティブのPythonリストに変換するには、ndarray.tolistを使用することをお勧めします。NumPy構造化配列の真に再帰的な `tolist()`

ああ、構造化配列を使用している場合、これは再帰的には機能していないようです。確かに、いくつかのndarrayオブジェクトは結果のリストで参照されている、未変換:

>>> dtype = numpy.dtype([('position', numpy.int32, 3)]) 
>>> values = [([1, 2, 3],)] 
>>> a = numpy.array(values, dtype=dtype) 
>>> a.tolist() 
[(array([1, 2, 3], dtype=int32),)] 

私はこの問題を回避するために簡単な関数を書いた:使用された場合

def array_to_list(array): 
    if isinstance(array, numpy.ndarray): 
     return array_to_list(array.tolist()) 
    elif isinstance(array, list): 
     return [array_to_list(item) for item in array] 
    elif isinstance(array, tuple): 
     return tuple(array_to_list(item) for item in array) 
    else: 
     return array 

、期待される結果を提供します、:

>>> array_to_list(a) == values 
True 

この機能に伴う問題は、それが出力する各リスト/タプルを再作成することによってndarray.tolistのジョブを複製することです。最適ではありません。

だから、質問は以下のとおりです。

  • が予想さndarray.tolistのこの行動のですか?
  • これを行うには良い方法がありますか?
+0

構造化された配列は、リストのリストよりもリストの値のほうが意味があります(またはその逆)。 – Evert

+0

Dictは構造化された配列のフィールドがdtype内で順序付きリストとして定義されているので、確かに実際には意味がありますがリストのリストもそうです。その上、NumPyは配列を初期化するために使われる 'values'変数を理解しています。非dict形式で定義されていますが、リストは確かに有効な構造体です。 – ChristopherC

答えて

0

ちょうどこの少しを一般化するために、私はあなたのDTYPEに別のフィールドを追加します

In [234]: dt = numpy.dtype([('position', numpy.int32, 3),('id','U3')]) 

In [235]: a=np.ones((3,),dtype=dt) 

repr表示はリストやタプルを使用します:

In [236]: a 
Out[236]: 
array([([1, 1, 1], '1'), ([1, 1, 1], '1'), ([1, 1, 1], '1')], 
    dtype=[('position', '<i4', (3,)), ('id', '<U3')]) 

ができますが、注意して、tolistは要素を展開しません。

In [237]: a.tolist() 
Out[237]: [(array([1, 1, 1]), '1'), (array([1, 1, 1]), '1'), 
    (array([1, 1, 1]), '1')] 

同様に、そのような配列は完全にネストされたリストとタプルから作成できます。

In [238]: a=np.array([([1,2,3],'str')],dtype=dt) 
In [239]: a 
Out[239]: 
array([([1, 2, 3], 'str')], 
    dtype=[('position', '<i4', (3,)), ('id', '<U3')]) 
In [240]: a.tolist() 
Out[240]: [(array([1, 2, 3]), 'str')] 

この不完全な再帰から、アレイを再作成も問題はありません:

In [250]: np.array(a.tolist(),dtype=dt) 
Out[250]: 
array([([1, 2, 3], 'str')], 
     dtype=[('position', '<i4', (3,)), ('id', '<U3')]) 

は、これは、私は誰もがこのような構造化された配列でtolistを使用し見てきたことを最初のですが、私はあまりにもありませんよ驚いた。開発者がこれをバグと見なすかどうかは分かりません。

なぜこの配列の純粋なリスト/タプルレンダリングが必要ですか?

これに対処する機能がnumpy/lib/recfunctions.pyにあるのだろうかと思います。

+0

単体テストを記述し、配列の内容を期待値を表す対応するネイティブPythonリストと比較したいときに、この問題を遭遇しました。他の方法もあるかもしれませんが、NumPyからPythonにデータを変換してassertIsEqualテストを使用することができました。終わりに、 'ndarray.tolist'はシリアライゼーションへの有効なアプローチだと思われますので、ここではうまくいきません。おそらく、NumPyのレポに関する問題を提出して、彼らがそれについて何を言っているのかを見てみよう。 – ChristopherC

+0

参考:https://github.com/numpy/numpy/issues/8052 – ChristopherC

関連する問題