numpy循环的替代方案和条件

时间:2017-03-25 18:24:15

标签: python performance numpy vectorization

我有2个非常大的numpy数组。如何根据条件得到array1中数组2的索引?条件是:对于array1中的每个值,找到数组2中的第一个值,并将索引 - 2复制到数组1.我希望这是有道理的。我在下面举例说明我的意思。

Numpy Array 1

+---------+------------+
| IndexNr |   Value    |
+---------+------------+
|       0 | 1485963480 |
|       1 | 1486029060 |
|       2 | 1486032900 |
|       3 | 1486032960 |
|       4 | 1486033020 |
|       5 | 1486033080 |
|       6 | 1486034940 |
|       7 | 1486038480 |
|       8 | 1486039140 |
|       9 | 1486039320 |
|      10 | 1486039500 |
|      11 | 1486041300 |
|      12 | 1486044360 |
|      13 | 1486048740 |
|      14 | 1486049880 |
|      15 | 1486049940 |
|      16 | 1486050240 |
|      17 | 1486114200 |
|      18 | 1486119840 |
|      19 | 1486119900 |
|      20 | 1486120380 |
|      21 | 1486134720 |
|      22 | 1486134780 |
|      23 | 1486135380 |
|      24 | 1486135440 |
+---------+------------+

Numpy Array 2

+---------+------------+
| IndexNr |   Value    |
+---------+------------+
|       0 | 1485963300 |
|       1 | 1486029000 |
|       2 | 1486032600 |
|       3 | 1486032900 |
|       4 | 1486034700 |
|       5 | 1486038300 |
|       6 | 1486038900 |
|       7 | 1486039200 |
|       8 | 1486041300 |
|       9 | 1486044300 |
|      10 | 1486048500 |
|      11 | 1486049700 |
|      12 | 1486114200 |
|      13 | 1486119900 |
|      14 | 1486120200 |
|      15 | 1486134600 |
+---------+------------+

这样的事情

+-------+-------------+
| Index | ArrayIndex2 |
+-------+-------------+
|     0 | nan         |
|     1 | nan         |
|     2 | nan         |
|     3 | 2           |
|     4 | 2           |
|     5 | 2           |
|     6 | 3           |
|     7 | 4           |
|     8 | 5           |
|     9 | 6           |
|    10 | 6           |
|    11 | 6           |
|    12 | 8           |
|    13 | 9           |
|    14 | 10          |
|    15 | 10          |
|    16 | 10          |
|    17 | 10          |
|    18 | 11          |
|    19 | 11          |
|    20 | 13          |
|    21 | 14          |
|    22 | 14          |
|    23 | 14          |
|    24 | 14          |
+-------+-------------+

这是我如何做到的解决方案。

import numpy as np

array1 = np.array([1486029060,1486032720,1486032900,1486032960,1486033020,1486033080,1486034940,1486038480,1486039140,1486039320,1486039500,1486041300,1486044360,1486048740,1486049880,1486049940,1486050240,1486114200,1486119840,1486119900,1486120380,1486134720,1486134780,1486135380,1486135440])
array2 = np.array([1485963300,1486029000,1486032600,1486032900,1486034700,1486038300,1486038900,1486039200,1486041300,1486044300,1486048500,1486049700,1486114200,1486119900,1486120200,1486134600])

# create an empty holder with the same size as array 1
array1_result = np.empty((array1.shape[0], 1))
array1_result.fill(np.nan)

# loop and create result array
for rowNr in range(array1.shape[0]):
    if (rowNr > 2):
        currentRowValue = array1[rowNr]
        array1_result[rowNr] = np.reshape(np.array(np.where(array2 < currentRowValue)), (-1, 1))[-2][0] #array2Index

print(array1_result)

唯一的问题是这个循环在大数组上非常低效。 array1和array2都是几百万行,使用这种方法非常慢。有没有其他方法可以达到相同的效果?

2 个答案:

答案 0 :(得分:1)

听起来像你想要searchsorted

>>> np.searchsorted(array2, array1)
array([ 2,  3,  3,  4,  4,  4,  5,  6,  7,  8,  8,  8, 10, 11, 12, 12, 12,
       12, 13, 13, 15, 16, 16, 16, 16], dtype=int64)

或编码你的&#34;但不是前两行&#34;条件

>>> np.searchsorted(array2, array1[2:]) - 2
array([ 1,  2,  2,  2,  3,  4,  5,  6,  6,  6,  8,  9, 10, 10, 10, 10, 11,
       11, 13, 14, 14, 14, 14], dtype=int64)
>>> np.concatenate(([0,0], _))
array([ 0,  0,  1,  2,  2,  2,  3,  4,  5,  6,  6,  6,  8,  9, 10, 10, 10,
   10, 11, 11, 13, 14, 14, 14, 14], dtype=int64)

这在一个地方不同意 - 1。我认为这是平等和不平等之间的区别

答案 1 :(得分:0)

如果没有初始nan值,则与您的array1_result匹配:

In [263]: A = array2<array1[3:,None]
In [264]: idx2 = np.sum(A,axis=1)-2
In [265]: idx2
Out[265]: 
array([ 2,  2,  2,  3,  4,  5,  6,  6,  6,  8,  9, 10, 10, 10, 10, 11, 11, 13, 14, 14, 14, 14])

A是一个(22,16)数组,True array2更小。我计算每行True的数量。其余的是调整2偏移量。