在pandas数据帧中查找每行的两列列表中哪一列的最快方法

Mar*_*rco 5 python performance numpy vectorization pandas

我正在寻找最快的方法来做到以下几点:

我们有一个pd.DataFrame:

df = pd.DataFrame({
    'High': [1.3,1.2,1.1],
    'Low': [1.3,1.2,1.1],
    'High1': [1.1, 1.1, 1.1],
    'High2': [1.2, 1.2, 1.2],
    'High3': [1.3, 1.3, 1.3],
    'Low1': [1.3, 1.3, 1.3],
    'Low2': [1.2, 1.2, 1.2],
    'Low3': [1.1, 1.1, 1.1]})
Run Code Online (Sandbox Code Playgroud)

看起来像:

In [4]: df
Out[4]:
   High  High1  High2  High3  Low  Low1  Low2  Low3
0   1.3    1.1    1.2    1.3  1.3   1.3   1.2   1.1
1   1.2    1.1    1.2    1.3  1.2   1.3   1.2   1.1
2   1.1    1.1    1.2    1.3  1.1   1.3   1.2   1.1
Run Code Online (Sandbox Code Playgroud)

我想知道的是High1,High2,High3浮点值中的哪一个是大于或等于High值的第一个.如果没有,那应该是np.nan

对于Low1,Low2,Low3值也是如此,但在这种情况下,其中一个是第一个低于或等于High值的值.如果没有,那应该是np.nan

最后,我需要知道哪一个,低或高是第一个.

解决这个问题的一种方法是以一种奇怪而不太高效的方式:

df['LowIs'] = np.nan
df['HighIs'] = np.nan

for i in range(1,4):
    df['LowIs'] = np.where((np.isnan(df['LowIs'])) & (
        df['Low'] >= df['Low'+str(i)]), i, df['LowIs'])
    df['HighIs'] = np.where((np.isnan(df['HighIs'])) & (
        df['High'] <= df['High'+str(i)]), i, df['HighIs'])

df['IsFirst'] = np.where(
    df.LowIs < df.HighIs,
    'Low',
    np.where(df.LowIs > df.HighIs, 'High', 'None')
)
Run Code Online (Sandbox Code Playgroud)

这给了我:

In [8]: df
Out[8]:
   High  High1  High2  High3  Low  Low1  Low2  Low3  LowIs  HighIs IsFirst
0   1.3    1.1    1.2    1.3  1.3   1.3   1.2   1.1    1.0     3.0     Low
1   1.2    1.1    1.2    1.3  1.2   1.3   1.2   1.1    2.0     2.0    None
2   1.1    1.1    1.2    1.3  1.1   1.3   1.2   1.1    3.0     1.0    High
Run Code Online (Sandbox Code Playgroud)

由于我必须在高/低不同的多次迭代中反复这样做,因此执行此操作时的性能至关重要.

所以我不介意High1,High2,High3和Low1,Low2,Low3是否会在一个单独的DataFrame中进行转置,或者它是否在dict或其他任何内容中.因此,在任何能够提供最佳性能的情况下准备数据的过程可能会变得缓慢而笨拙.

我工作的一个解决方案,但是无法完成以矢量化方式工作,而且似乎也很慢:

df.loc[(df.index == 0), 'HighIs'] = np.where(
    df.loc[(df.index == 0), ['High1', 'High2', 'High3']] >= 1.3
)[1][0] + 1
Run Code Online (Sandbox Code Playgroud)

因此,检查第一行中哪一列是真的,然后查看np.where()的索引号.

期待任何建议,并希望学到新的东西!:)

Div*_*kar 1

这是一种矢量化方法NumPy broadcasting-

a = df.values
out1 = (a[:,1:4] >= a[:,0,None]).argmax(1)+1
out2 = (a[:,5:8] <= a[:,4,None]).argmax(1)+1
df['LowIs'] = out2
df['HighIs'] = out1
df['IsFirst'] = np.where(out1!=out2,np.where(out1 > out2, 'Low', 'High'),None)
Run Code Online (Sandbox Code Playgroud)

示例输出 -

In [195]: df
Out[195]: 
   High  High1  High2  High3  Low  Low1  Low2  Low3  LowIs  HighIs IsFirst
0   1.3    1.1    1.2    1.3  1.3   1.3   1.2   1.1      1       3     Low
1   1.2    1.1    1.2    1.3  1.2   1.3   1.2   1.1      2       2    None
2   1.1    1.1    1.2    1.3  1.1   1.3   1.2   1.1      3       1    High
Run Code Online (Sandbox Code Playgroud)