Python 基于非索引数组的另一个数组中的值,从numpy数组中选择元素

Python 基于非索引数组的另一个数组中的值,从numpy数组中选择元素,python,numpy,Python,Numpy,假设我有以下两个数组: 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, '

假设我有以下两个数组:

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=数组([(1,'L',74.423088306605),(5,'H',128.05441039929008),
(2,'L',68.0581377353869),(0,'H',88.15726964130869),
(4,'L',97.45015828212),(3,'H',92.98550136344437),
(7,'L',87.75945631669309),(6,'L',90.43196739694255),
(8,'H',111.13662092749307),(15,'H',91.44444 608631304),
(10,'L',85.43615908319185),(11,'L',78.1168566130103494),
(13,'H',108.2841293816308),(17,'L',74.43917911042259),
(14,'H',64.41057325770373),(9,'L',27.407214746467943),
(16,'H',81.505064434964355),(12,'H',97.79700070323196),
(19,'L',51.139258140713025),(18,'H',118.34835768605957)],

dtype=[('id','你应该用这个得到你想要的

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')])
indes=[i代表i,枚举中的id(a['id']),如果id在b中]
suba=a[指数]
打印(suba)
>>>数组([(5,'H',128.05441039929008),(0,'H',88.15726964130869),
(3,'H',92.98550136344437),(8,'H',111.13662092749307),
(15,'H',91.44444 608631304),(13,'H',108.2841293816308),
(14,'H',64.41057325770373),(16,'H',81.505064434964355),
(12,'H',97.79700070323196),(18,'H',118.34835768605957)],
dtype=[('id','
sorted=numpy.sort(a)
分类[b]
数组([(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.44444 608631304),
(16,'H',81.505064434964355),(18,'H',118.34835768605957)],

dtype=[('id','以下方法的运行速度比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
它是一个数组,包含的行数与
b
中的元素数相同,列数与
a
中的元素数相同。argmax
然后查找每行中第一个
True
的位置,这是
a['id']
b
对应元素的第一次出现的索引

如上所示,对于小型数组,这在性能上优于python。但是如果
a
b
变得太大,那么
bool
s中间数组的大小可能会削弱性能。此外,
np.argmax
必须搜索整行,它永远不会提前跳出循环,如果
>a
太长了。我在使用类似方法的答案中做了一些计时,但对于中等规模的阵列,仍然有一条路要走


Francesco的方法肯定不那么粗糙,更容易理解,我必须承认,对于样本大小的数组来说,性能差异是无关紧要的。但这并不会让你觉得…

谢谢!这似乎很好。如果我在某个时候看不到更好的答案,我会接受这个。我不想依赖排序。我想要我认为第一行应该被排序为=numpy.argsort(a),在这种情况下,它对排序是健壮的。哇,这太神奇了,尽管我不能说我理解
[None,:]背后的逻辑
。只是好奇:你知道你的方法的伸缩性吗?天真的我会说我的方法的伸缩性大致与a和b的大小成线性(如果
如果b中的id
是懒惰的,伸缩性更好)@FrancescoMontesano这正是问题所在,我认为这是O(n**2),我认为你的方法更好,尽管根据我的说法,你可能需要将
b
转换成
集才能实现这一点。因此,最终你的方法将是最快的,但对于非常大范围的较小规模,python的慢度,或者numpy/C的速度都是无关紧要的。@FrancescoMontesano
[None,:]
相当于
。重塑(1,-1)
,它将一维数组转换为列向量。因此,当它比较列向量和行向量时,它将它们广播到完整的矩形形状。明白了!我(想我)不知道这种广播。感谢您的解释
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)