2016-04-12 6 views
0

は、私は、次のnumpyの配列があるとします。委任呼び出し

arr = np.array(["a", "b", "c"], dtype=object) 

今、私は任意の関数を実行するか、各要素上の任意のメソッドを呼び出します。たとえば、これらすべての要素の大文字を取得したいとします。

upp_arr = arr.upper() 

または

upp_arr = str.upper(arr) 

ショートバージョン:「論理的」に言えば、私はこのような何かをしたいのですが、私はどちらかは、上記の達成することができますか?

ロングバージョン: は、これは明らかに(個々の要素がない場合でも)upperメソッドを持っていない配列を考慮し、仕事に行くされていない、またstrビルトインはnumpyの配列を処理する方法を知っています。配列を扱う方法を知っているstr.upperのカスタムバージョンを構築したくないのです。それは、配列のユーザーが使用したい機能を事前に知っておく必要があるからです。

でも、私は

upp_arr = np.array([x.upper() for x in arr]) 

私はこれが好きではないような何かを行うことができます:今、私はarrが実際にnumpyの配列であることを私のコードのユーザーに公開する必要があります。私は上記の2つの非機能的なソリューションのようなものを入手したい。

私はnp.ndarrayをサブクラス化によってこれを実現するために試みたが、namenp.ndarrayの属性でない場合、名前nameの要素の属性の配列を返すように__getattr__(self, name)メソッドを上書きし、にその__call__メソッドを上書き要素の配列コール `結果を返します:

import numpy as np 

class MyArr(np.ndarray): 
    def __getattr__(self, name): 
     if hasattr(np.ndarray, name): 
      return getattr(np.ndarray, name) 
     arr = MyArr(self.shape, dtype=object) 
     arr[:] = [getattr(elem, name) for elem in self] 
     return arr 
    def __call__(self): 
     arr = MyArr(self.shape, dtype=self.dtype) 
     arr[:] = [elem() for elem in self] 
     return arr 

arr = MyArr((3,), dtype=object) 
arr[:] = ["a", "b", "c"] 
arr.upper() 

これは二つの問題があります。配列を構築することはお尻の痛みですが、(最初にそれをインスタンス化し、その後、値でそれを埋めるために持っている)と、私は、 f関数呼び出しは元の配列(dtype=self.dtype部分)と同じdtypeです。この後者は、objectタイプの配列に固執すれば問題はありませんが、一般的になります。

どうすれば解決できますか?

+0

コンストラクトと塗りつぶしに問題はありません。 'numpy'は常にそれを行います。 'vectorize'は一つの値を評価し、その結果を使ってreturn dtypeを設定します。時々それはSOの質問を引き起こす。 – hpaulj

答えて

-1

str操作を文字列配列の要素に適用する関数ライブラリがあります。

In [199]: np.char.upper(np.array(['a','b','c'])) 
Out[199]: 
array(['A', 'B', 'C'], 
     dtype='|S1') 

しかし、それはDTYPEオブジェクトの配列では動作しません:

In [200]: np.char.upper(np.array(['a','b','c'],dtype=object)) 
--------------------------------------------------------------------------- 
TypeError         Traceback (most recent call last) 
<ipython-input-200-17a9e3cc581f> in <module>() 
----> 1 np.char.upper(np.array(['a','b','c'],dtype=object)) 
...\numpy\core\defchararray.pyc in upper(a) 
    1571  """ 
    1572  a_arr = numpy.asarray(a) 
-> 1573  return _vec_string(a_arr, a_arr.dtype, 'upper') 
TypeError: string operation on non-string array 

しかし、このchar機能は、任意のより速い対応するリスト内包以上ではありません。各要素に対してstr操作を呼び出さなければなりません。しかし、配列がn-dならば、より便利になるでしょう。

In [209]: timeit np.char.upper(x1) # large x1 
1000 loops, best of 3: 277 µs per loop 

In [210]: timeit np.array([i.upper() for i in x1]) 
1000 loops, best of 3: 278 µs per loop 

問題に関するいくつかの新しい考え。

np.frompyfuncは、配列のすべての要素に関数を適用し、新しいオブジェクトdtype配列を返します。

In [49]: vupper = np.frompyfunc(lambda astr: astr.upper(), 1, 1) 
In [50]: vupper(np.array(['a','b','c'])) 
Out[50]: array(['A', 'B', 'C'], dtype=object) 
In [51]: vupper(np.array(['a','b','c'], dtype=object)) 
Out[51]: array(['A', 'B', 'C'], dtype=object) 

np.vectorizenp.frompyfuncを使用していますが、いくつかdtype変換を追加します。私のテストでは、np.frompyfuncは少し速いです。いくつかのケースでは同等のリスト理解版よりも2倍高速です。

np.recarrayが属性として構造化配列フィールドにアクセスする方法を確認するには、numpy/core/records.pyを参照してください。それは__getattribute__を包みます。

マスクされた配列は、カスタムメソッドの大きなコレクションを持つ配列サブクラスの良い例です。 /numpy/ma/__init__.py

+0

これはまだ機能のセットです。私は_any_関数で動作するソリューションを探しています。 – acdr