Python 如何矢量化数据帧正向列值搜索

Python 如何矢量化数据帧正向列值搜索,python,pandas,dataframe,vectorization,Python,Pandas,Dataframe,Vectorization,我只想在pandas dataframe列中正向搜索目标值,如果找到更大的值,我想将索引差异记录为结果列。我已经设法做到这一点,两个内部的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=

我只想在pandas dataframe列中正向搜索目标值,如果找到更大的值,我想将索引差异记录为结果列。我已经设法做到这一点,两个内部的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
我们的第一个值是8,目标值是12。我们期待在“价值”列中找到超过此目标值的价值。我们在第4行找到它,值为16。我想记录的是指数差,它是4-0=4

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

让我们跳到第四排。我们开始从指数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

不使用for循环可以做到这一点吗?

使用numpy广播进行比较,将numpy上三角矩阵设置为
False
,将第一个
True
索引设置为,减去
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

您可以将其缩短为一个for循环。使用和布尔条件:

df['Result'] = 0
for i, target in enumerate(df.Target):
    val = df[(df.Value>target) & (df.index>i)]['Value'].first_valid_index()
    if val is not None:
        df.at[i, 'Result'] = val - i
df
   Value    Target  Result
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

条件查找
大于目标值的每一行,但也仅在目标索引之后,并且
第一个有效索引
将返回满足条件的第一个索引。

这是一个很好的答案,肯定满足了要求。但在我的例子中,当我尝试将其用于我的真实数据集时,不幸的是,我的内存不足。我认为,如果你没有足够的资源,就没有什么可以做的了。这仍然是纯粹的天才。