4

手っ取り早い問題

同じdtypeを持つことが保証されている2つのnumpy構造化配列から特定のdtypeフィールドを比較できるようにしたいと考えています。特定の入力に基づいて関数が呼び出されるたびに、比較するフィールドが異なるようにする方法でこれを行いたいと思います (つまり、個々のフィールドごとに比較を簡単にハードコーディングすることはできません)。

例の長い問題

同じ dtype を持つ 2 つの numpy 構造化配列の特定のフィールドを比較しようとしています。たとえば、私たちが持っているとしましょう

import numpy as np
from io import BytesIO

a = np.genfromtxt(BytesIO('12 23 0|23.2|17.9|0\n12 23 1|13.4|16.9|0'.encode()),dtype=[('id','U7'),('pos',[('x',float),('y',float)]),('flag','U1')],delimiter='|')

b = np.genfromtxt(BytesIO(' |23.0|17.91|0'.encode()),dtype=[('id','U7'),('pos',[('x',float),('y',float)]),('flag','U1')],delimiter='|')

を与える

In[156]: a
Out[154]: 
array([('12 23 0', (23.2, 17.9), '0'), ('12 23 1', (13.4, 16.9), '0')], 
      dtype=[('id', '<U7'), ('pos', [('x', '<f8'), ('y', '<f8')]), ('flag', '<U1')])

In[153]: b
Out[151]: 
array([('', (23.0, 17.91), '0')], 
      dtype=[('id', '<U7'), ('pos', [('x', '<f8'), ('y', '<f8')]), ('flag', '<U1')])

aここで、フィールドがa['pos']['x']フィールドより大きいエントリをチェックして見つけ、b['pos']['x']これらのエントリを新しい numpy 配列に返したいとしましょう。

newArr = a[a["pos"]["x"]>b["pos"]["x"]]

ここで、とフィールドaの両方が の対応するものよりも大きいエントリのみを保持したいとします。これは非常に簡単です。xyb

newArr = a[np.array([np.array([a['pos']['x']>b['pos']['x']),a['pos']['y']>b['pos']['y'])).all(axis=0)]

これは正しい答えである空の配列を返します。

ただし、これらの配列に非常に複雑な dtype があり (たとえば、34 個のフィールドがあるとします。使用している dtype の例については、こちらを参照してください)、それらのいずれかを比較できるようにしたいが、すべてを比較できるようにしたいとします。 (前の例に似ていますが、全体的により多くの dtype フィールドがあり、比較したいものも多くあります。さらに、比較したいフィールドが実行ごとに変化する可能性がある場合はどうなるでしょうか (したがって、実際にハードコーディングすることはできません)上記で行った方法)それが私が解決策を見つけようとしている問題です。

私の現在の(未完の)解決策の試み

マスクされた配列の使用

この問題を解決するために最初に考えたのは、マスクされた配列を使用して、比較するデータ型フィールドを選択することでした。このようなもの(すべての比較を同じにできると仮定して):

mask = np.ones(z.shape,dtype=[('id',bool),('pos',[('x',bool),('y',bool)]),('flag',bool)])
# unmask the x and y fields so we can compare them 
mask['pos']['x']=0
mask['pos']['y']=0

maskedA = np.ma.masked_array(a, mask=mask)
# We need to do this or the masked array gets angry (at least in python 3)
b.shape = (1,)

maskedB = np.ma.masked_array(b, mask=mask)

今、私は次のようなことをしたいと思います

test = (maskedA>maskedB).any(axis=1)

しかし、構造化された配列を次のように比較できるため、これは機能しません --

TypeError: unorderable types: MaskedArray() > MaskedArray()

また、マスクされた配列を圧縮しようとしました

test = (maskedA.compressed()>maskedB.compressed()).any(axis=1)

その結果、別のエラーが発生します

TypeError: ufunc 'logical_not' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

さて、構造化されたマスク配列がどのように機能するかを完全に理解していないため、上記のエラーが発生する可能性が高いことに気付きましたが、それが部分的にこの質問をしている理由です。マスクされた配列を使用してこのようなことを行う方法はありますか?

私が考えた解決策はおそらくうまくいくでしょうし、おそらく全体的により良いでしょう...

したがって、これを書いているときに考えたもう1つのオプションは、ユーザーの入力を解析して配列を形成するときに比較を行うことbです。実際には、パーサーの各条件に数行を追加して比較を行い、結果を numpy ブール配列に追加してから、適切なエントリを抽出するために使用できますa。今思えば、これでいいのかもしれません。

私の長くとりとめのない問題の結論。

この問題の解決策を見つけたと思うという事実にもかかわらず、少なくとも少しの間、この質問を投稿して、(a)構造化された/マスクされたnumpy配列との論理比較を行う方法についてアイデアがあるかどうかを確認します。知っておくと便利なことだと思います.(b)誰かが私が思いついたものよりも良いアイデアを持っているかどうかを確認してください. 「例に関する長い問題」セクションのスニペットを 1 行ずつコピーすることで MWE を非常に簡単に作成できることに注意してください。

4

2 に答える 2