5

次の2つの配列があるとします。

a = array([(1, 'L', 74.423088306605), (5, 'H', 128.05441039929008),
       (2, 'L', 68.0581377353869), (0, 'H', 88.15726964130869), 
       (4, 'L', 97.4501582588212), (3, 'H', 92.98550136344437),
       (7, 'L', 87.75945631669309), (6, 'L', 90.43196739694255),
       (8, 'H', 111.13662092749307), (15, 'H', 91.44444608631304),
       (10, 'L', 85.43615908319185), (11, 'L', 78.11685661303494),
       (13, 'H', 108.2841293816308), (17, 'L', 74.43917911042259),
       (14, 'H', 64.41057325770373), (9, 'L', 27.407214746467943),
       (16, 'H', 81.50506434964355), (12, 'H', 97.79700070323196),
       (19, 'L', 51.139258140713025), (18, 'H', 118.34835768605957)], 
      dtype=[('id', '<i4'), ('name', 'S1'), ('value', '<f8')])

b = array([ 0,  3,  5,  8, 12, 13, 14, 15, 16, 18], dtype=int32)

で指定されaている要素を選択したい。つまり、はインデックス配列ではありません。観測値が含まれています。どうすればこれをnumpyで行うことができますか?idbbids

助けてくれてありがとう。

4

3 に答える 3

5

以下は、サンプル配列に対するFrancescoのアプローチよりも数倍高速に機能します。

In [7]: a[np.argmax(a['id'][None, :] == b[:, None], axis=1)]
Out[7]: 
array([(0, 'H', 88.15726964130869), (3, 'H', 92.98550136344437),
       (5, 'H', 128.05441039929008), (8, 'H', 111.13662092749307),
       (12, 'H', 97.79700070323196), (13, 'H', 108.2841293816308),
       (14, 'H', 64.41057325770373), (15, 'H', 91.44444608631304),
       (16, 'H', 81.50506434964355), (18, 'H', 118.34835768605957)], 
      dtype=[('id', '<i4'), ('name', '|S1'), ('value', '<f8')])

In [8]: %timeit a[np.argmax(a['id'][None, :] == b[:, None], axis=1)]
100000 loops, best of 3: 11.6 us per loop

In [9]: %timeit indices = [i for i,id in enumerate(a['id']) if id in b]; a[indices]
10000 loops, best of 3: 66.9 us per loop

それがどのように機能するかを理解するには、これを見てください:

In [10]: a['id'][None, :] == b[:, None]
Out[10]: 
array([[False, False, False,  True, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False, False],
    ... # several rows removed 
    [False, False, False, False, False, False, False, False, False,
        False, False, False, False, False, False, False, False, False,
        False,  True]], dtype=bool)

これは、の要素と同じ数の行との要素bと同じ数の列の配列ですanp.argmax次に、すべての行の最初の位置を見つけますTrue。これは、の対応する要素の最初の出現のインデックスbですa['id']

上に示したように、小さな配列の場合、これはPythonのパフォーマンスを上回ります。ただし、どちらabが大きくなりすぎると、boolsの中間配列のサイズによってパフォーマンスが低下する可能性があります。また、np.argmax行全体を検索する必要があり、ループから早く抜け出すことはありません。これは、a長すぎる場合は適切ではありません。同様のアプローチを使用するこの質問への回答でいくつかのタイミングを実行しましたが、それでも適度に大きなアレイを選択する方法がありました。

Francescoのアプローチは間違いなくハックが少なく、理解しやすく、サンプルのサイズの場合、パフォーマンスの違いは関係ありません。認めなければなりません。しかし、それはあなたがこのように感じることはありません...

于 2013-02-07T17:36:28.093 に答える
5

あなたはこれであなたが望むものを手に入れるべきです

indeces = [i for i,id in enumerate(a['id']) if id in b]
suba = a[indeces]
print(suba)
>>>array([(5, 'H', 128.05441039929008), (0, 'H', 88.15726964130869),
   (3, 'H', 92.98550136344437), (8, 'H', 111.13662092749307),
   (15, 'H', 91.44444608631304), (13, 'H', 108.2841293816308),
   (14, 'H', 64.41057325770373), (16, 'H', 81.50506434964355),
   (12, 'H', 97.79700070323196), (18, 'H', 118.34835768605957)], 
  dtype=[('id', '<i4'), ('name', '|S1'), ('value', '<f8')])
于 2013-02-07T16:16:49.867 に答える
0
sorted = numpy.sort(a)
sorted[b]
 array([(0, 'H', 88.15726964130869), (3, 'H', 92.98550136344437),
   (5, 'H', 128.05441039929008), (8, 'H', 111.13662092749307),
   (12, 'H', 97.79700070323196), (13, 'H', 108.2841293816308),
   (14, 'H', 64.41057325770373), (15, 'H', 91.44444608631304),
   (16, 'H', 81.50506434964355), (18, 'H', 118.34835768605957)], 
  dtype=[('id', '<i4'), ('name', '|S1'), ('value', '<f8')])

配列内の行と同じ数のIDがある限り。

于 2013-02-07T16:17:21.863 に答える