如何矢量化熊猫数据框正向列值搜索

aki*_*net 5 python vectorization dataframe pandas

我想仅在向前方向上搜索熊猫数据帧列中的目标值,如果找到更大的值,那么我想将索引差异记录为结果列。我已经设法用两个内部 for 循环来做到这一点,但它非常缓慢。

这就是我想在一个简化的例子中实现的目标。

import pandas as pd

d = {
    'Value'  : [8,9,10,12,16,13,11,7,12,18],
    'Target' : [12,12,11,15,19,11,16,11,17,18]
    }
df = pd.DataFrame(data=d)


>>> df

   Target  Value
0      12      8
1      12      9
2      11     10
3      15     12
4      19     16
5      11     13
6      16     11
7      11      7
8      17     12
9      18     18
Run Code Online (Sandbox Code Playgroud)

我们的第一个值是 8,我们的目标值是 12。我们期待在值列中找到一个超过这个目标值的值。我们在第 4 行找到它,值为 16。我要记录的是索引差异,即 4-0=4。

下一个值是 9,目标值是 12。我们向前看值并再次找到第 4 行,值为 16。现在索引差为 4-1=3

让我们跳到第 4 行。我们开始从索引 5 开始寻找目标值。如果没有找到值,则结果为 0。

这是我想要达到的结果列。

   Target  Value  Result
0      12      8       4
1      12      9       3
2      11     10       1
3      15     12       1
4      19     16       0
5      11     13       3
6      16     11       3
7      11      7       1
8      17     12       1
9      18     18       0
Run Code Online (Sandbox Code Playgroud)

这可以在没有 for 循环的情况下完成吗?

jez*_*ael 5

使用 numpy 广播进行比较,将 numpy 上三角矩阵设置为False,通过 获取第一个True索引numpy.argmax,减去arange并设置为0所有负数:

t = df['Target'].values[:, None]
v = df['Value'].values
m = v > t
m[np.tril_indices(m.shape[1])] = False
print (m)
[[False False False False  True  True False False False  True]
 [False False False False  True  True False False False  True]
 [False False False  True  True  True False False  True  True]
 [False False False False  True False False False False  True]
 [False False False False False False False False False False]
 [False False False False False False False False  True  True]
 [False False False False False False False False False  True]
 [False False False False False False False False  True  True]
 [False False False False False False False False False  True]
 [False False False False False False False False False False]]

a = np.argmax(m, axis=1) - np.arange(len(df))
print (a)
[ 4  3  1  1 -4  3  3  1  1 -9]

df['new'] = np.where(a > 0, a, 0)
print (df)
   Value  Target  new
0      8      12    4
1      9      12    3
2     10      11    1
3     12      15    1
4     16      19    0
5     13      11    3
6     11      16    3
7      7      11    1
8     12      17    1
9     18      18    0
Run Code Online (Sandbox Code Playgroud)