Python 使用矢量化将列查找值相乘的更快方法

Python 使用矢量化将列查找值相乘的更快方法,python,pandas,numpy,dataframe,Python,Pandas,Numpy,Dataframe,我有两个数据帧,一个包含值,是工作数据集(postsolutionDF),而另一个只是作为查找表(FactoryPortPCNTDF)参考。目标是向postsolutionDF添加一列,该列包含postsolutionDF每行的查找值的乘积(新列名=num_predict)。然后将该乘积乘以2700。例如,在第一行上,工作值为0.5,2,-6。这些的等效查找值为0.1182、0.2098和0.8455。它们的乘积是0.0209,当乘以2700时,结果是56.61,如输出所示 下面的代码适用于这个

我有两个数据帧,一个包含值,是工作数据集(postsolutionDF),而另一个只是作为查找表(FactoryPortPCNTDF)参考。目标是向postsolutionDF添加一列,该列包含postsolutionDF每行的查找值的乘积(新列名=num_predict)。然后将该乘积乘以2700。例如,在第一行上,工作值为0.5,2,-6。这些的等效查找值为0.1182、0.2098和0.8455。它们的乘积是0.0209,当乘以2700时,结果是56.61,如输出所示

下面的代码适用于这个简化的示例,但在实际解决方案中速度非常慢(1.6MM行x 15个编号列)。我确信有一个更好的方法可以通过删除“fork 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

我不知道如何在本地熊猫身上做到这一点,但如果你回到努比,这是相当容易的

该函数设计用于在查找表中的值之间进行插值,但如果输入值与查找表中的值完全匹配(就像您的一样),则它将变成一个简单的查找,而不是插值

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
我必须填充factorymportpcntdf,以便所有列都有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
etc列需要按递增顺序排列(您的列在这里,仅供参考)。否则,interp将运行,但不一定会给出好的结果。

您能解释第2行吗?我理解第1行阅读您的问题,但不理解如何处理第2行。两个DFs中的索引是否相互对应?也就是说,
factorymportpcntdf
中的索引0是在
postsolutionDF
中查找索引0吗?如果是,或者如果您有任何其他方法将数据帧合并为一个,您可以轻松地将计算矢量化。我可以看到您的DFs具有不同的长度,这表明索引不对应。另外,
postsolutionDF
中的
[“1”、“2”、“3”]
列似乎与第一行的
[“F1\u Val”、“F2\u Val”、“F3\u Val”]
列相匹配,但与其他行不匹配,这表明我们也无法在这些行上合并。索引不对应。postsolutionDF索引上升到约1.6MM,而factorimportpcntDF索引在所示的4行中是静态的。postsolutionDF中的列与factorimportpcntDF中的列相对应。例如,postsolutionDF中的列“1”将始终对应于FactoryPortPCNTDF中的查找列“F1_-Val”,以及FactoryPortPCNTDF中的结果值列“F1_-Pcnt”。实际上,您可以根据factorymportpcntdf中的“F1_Val”和“F1_Pcnt”列,为postsolutionDF中的每个编号列创建一个查找dict。非常重要的澄清!