将列查找值与矢量化相乘的更快方法

时间:2019-01-25 02:36:47

标签: python pandas numpy dataframe

我有两个数据框,一个包含值并且是工作数据集(postsolutionDF),而另一个仅作为查找表(factorimportpcntDF)的参考。目标是在postsolutionDF中添加一列,其中包含来自postsolutionDF每行的查找值的乘积(新列名称= num_predict)。然后将该乘积乘以2700。例如,在第一行上,工作值为0.5、2,-6。这些的等效查询值为0.1182、0.2098和0.8455。它们的乘积是0.0209,乘以2700就是56.61,如输出所示。

下面的代码适用于此简化示例,但在实际解决方案中速度非常慢(1.6MM行x 15编号列)。我确信通过删除“ for k in range”循环可以找到一种更好的方法,但是由于已经在行上使用了apply,所以我一直在努力。我找到了许多切线解决方案,但还没有一种适合我的情况。感谢您的帮助。

import pandas as pd
import numpy as np

postsolutionDF = pd.DataFrame({'SCRN' : (['2019-01-22-0000001', '2019-01-22-0000002', '2019-01-22-0000003']), '1' : 0.5,
                               '2' : 2, '3' : ([-6, 1.0, 8.0])})
postsolutionDF = postsolutionDF[['SCRN', '1', '2', '3']]
print('printing initial postsolutionDF..')
print(postsolutionDF)

factorimportpcntDF = pd.DataFrame({'F1_Val' : [0.5, 1, 1.5, 2], 'F1_Pcnt' : [0.1182, 0.2938, 0.4371, 0.5433], 'F2_Val'
: [2, 3, np.nan, np.nan], 'F2_Pcnt' : [0.2098, 0.7585, np.nan, np.nan], 'F3_Val' : [-6, 1, 8, np.nan], 'F3_Pcnt' :
    [0.8455, 0.1753, 0.072, np.nan]})

print('printing factorimportpcntDF..')
print(factorimportpcntDF)

def zero_filter(row): # row is series
    inner_value = 1
    for k in range(1, 4): # number of columns in postsolutionDF with numeric headers, dynamic in actual code
        inner_value *= factorimportpcntDF.loc[factorimportpcntDF['F'+str(k)+'_Val']==row[0+k], 'F'+str(k)+'_Pcnt'].values[0]
    inner_value *= 2700
    return inner_value

postsolutionDF['num_predict'] = postsolutionDF.apply(zero_filter, axis=1)
print('printing new postsolutionDF..')
print(postsolutionDF)

打印输出:

C:\ProgramData\Anaconda3\python.exe C:/Users/Eric/.PyCharmCE2017.3/config/scratches/scratch_5.py
printing initial postsolutionDF..
                 SCRN    1  2    3
0  2019-01-22-0000001  0.5  2 -6.0
1  2019-01-22-0000002  0.5  2  1.0
2  2019-01-22-0000003  0.5  2  8.0
printing factorimportpcntDF..
   F1_Pcnt  F1_Val  F2_Pcnt  F2_Val  F3_Pcnt  F3_Val
0   0.1182     0.5   0.2098     2.0   0.8455    -6.0
1   0.2938     1.0   0.7585     3.0   0.1753     1.0
2   0.4371     1.5      NaN     NaN   0.0720     8.0
3   0.5433     2.0      NaN     NaN      NaN     NaN
printing new postsolutionDF..
                 SCRN    1  2    3  num_predict
0  2019-01-22-0000001  0.5  2 -6.0    56.610936
1  2019-01-22-0000002  0.5  2  1.0    11.737312
2  2019-01-22-0000003  0.5  2  8.0     4.820801

Process finished with exit code 0

1 个答案:

答案 0 :(得分:0)

我不确定如何在本地大熊猫中做到这一点,但是如果您返回numpy,这非常简单。

numpy.interp函数旨在在查询表中的值之间进行插值,但是如果输入值与查询表中的值完全匹配(就像您的操作一样),它将变成简单的查询,而不是插值

postsolutionDF['1new'] = np.interp(postsolutionDF['1'].values, factorimportpcntDF['F1_Val'], factorimportpcntDF['F1_Pcnt'])
postsolutionDF['2new'] = np.interp(postsolutionDF['2'].values, factorimportpcntDF['F2_Val'], factorimportpcntDF['F2_Pcnt'])
postsolutionDF['3new'] = np.interp(postsolutionDF['3'].values, factorimportpcntDF['F3_Val'], factorimportpcntDF['F3_Pcnt'])
postsolutionDF['num_predict'] = postsolutionDF['1new'] * postsolutionDF['2new'] * postsolutionDF['3new'] * 2700
postsolutionDF.drop(columns=['1new', '2new', '3new'], inplace=True)

给出输出:

In [167]: postsolutionDF
Out[167]: 
                 SCRN    1  2    3  num_predict
0  2019-01-22-0000001  0.5  2 -6.0    56.610936
1  2019-01-22-0000002  0.5  2  1.0    11.737312
2  2019-01-22-0000003  0.5  2  8.0     4.820801

我必须填充factorimportpcntDF,以便所有列都具有4个值,否则查找列的最高值将不起作用。您可以多次使用相同的值,也可以根据需要将其拆分为3个查询表,这样列的长度可以不同。

factorimportpcntDF = pd.DataFrame({'F1_Val' : [0.5, 1, 1.5, 2], 'F1_Pcnt' : [0.1182, 0.2938, 0.4371, 0.5433],
'F2_Val' : [2, 3, 3, 3], 'F2_Pcnt' : [0.2098, 0.7585, 0.7585, 0.7585],
'F3_Val' : [-6, 1, 8, 8], 'F3_Pcnt' : [0.8455, 0.1753, 0.072, 0.072]})

请注意,文档指定F1_val等栏必须按升序排列(您在这里只是FYI)。否则,interp会运行,但不一定会产生良好的结果。