Python 基于列插值的pandas连接
我正在尝试基于这两列连接两个数据帧。问题是我想插值其中一个列值Python 基于列插值的pandas连接,python,pandas,merge,interpolation,Python,Pandas,Merge,Interpolation,我正在尝试基于这两列连接两个数据帧。问题是我想插值其中一个列值 df1 = pd.DataFrame(data=[['ABC', 'USD', 2.31], ['DEF', 'MXN', 4.72], ['XYZ', 'EUR', 5.83]], columns=['A', 'B', 'C']) >>df1 A B C 0 ABC USD 2.31 1 DEF MXN 4.72 2 XYZ EUR 5.83 df2 = pd.DataFram
df1 = pd.DataFrame(data=[['ABC', 'USD', 2.31], ['DEF', 'MXN', 4.72], ['XYZ', 'EUR', 5.83]], columns=['A', 'B', 'C'])
>>df1
A B C
0 ABC USD 2.31
1 DEF MXN 4.72
2 XYZ EUR 5.83
df2 = pd.DataFrame(data=[['USD', 1, 0.5], ['USD', 2, 0.8], ['USD', 3, 1.5], ['MXN', 2, 0.6], ['MXN', 3, 0.71], ['MXN', 4, 0.88], ['EUR', 6, 0.12], ['EUR', 7, 0.5], ['EUR', 8, 0.7]], columns=['B', 'C', 'V'])
>>df2
B C V
0 USD 1 0.50
1 USD 2 0.80
2 USD 3 1.50
3 MXN 2 0.60
4 MXN 3 0.71
5 MXN 4 0.88
6 EUR 6 0.12
7 EUR 7 0.50
8 EUR 8 0.70
我希望将基于B列和C列的两个数据帧连接起来,以便得到以下结果
A B C V
0 ABC USD 2.31 1.017
1 DEF MXN 4.72 0.880
2 XYZ EUR 5.83 0.120
插值是线性的,超出范围时使用最近的点
第一个值
1.017=0.8+(2.31-2)*(1.5-0.8)
第二个值存在,因为df2中MXN的最大值为0.6
第三个值也是欧元的最大值,即0.12
目标是尽可能高效地完成这项工作,因为数据帧非常大
到目前为止,我正在按B分组并使用scipy插值函数。这是我提出的解决方案,尽管我认为您可能可以通过在插值步骤中使用apply with
scipy.interpolate
来改进这一点。首先为df1创建楼板、天花板和三角柱
enter df1['C_floor'] = df1.C.apply(np.floor)
df1['C_ceil'] = df1.C.apply(np.ceil)
df1['C_delta'] = df1.C - df1.C_floor
从df2
进行左双连接,以获得与C
的地板和天花板相对应的V
df1 = df1.merge(df2, how ='left', left_on = ['B', 'C_floor'], right_on = ['B', 'C'])
df1 = df1.merge(df2, how ='left', left_on = ['B', 'C_ceil'], right_on = ['B', 'C'])
def weighted_mean(x):
if np.isnan(x.V_x):
return x.V_y
elif np.isnan(x.V_y):
return x.V_x
else:
return x.V_y + (x.V_x - x.V_y) * x.C_delta
df1['V'] = df1[['V_x', 'V_y', 'C_delta']].apply(weighted_mean, axis = 1)
在这里,我认为您可以使代码更快,但我编写了一个简短的函数来查找加权平均值,并解释C
超出df2
可用范围的情况
df1 = df1.merge(df2, how ='left', left_on = ['B', 'C_floor'], right_on = ['B', 'C'])
df1 = df1.merge(df2, how ='left', left_on = ['B', 'C_ceil'], right_on = ['B', 'C'])
def weighted_mean(x):
if np.isnan(x.V_x):
return x.V_y
elif np.isnan(x.V_y):
return x.V_x
else:
return x.V_y + (x.V_x - x.V_y) * x.C_delta
df1['V'] = df1[['V_x', 'V_y', 'C_delta']].apply(weighted_mean, axis = 1)
最后是一些清理
df1 = df1[['A', 'B', 'C_x', 'V']]
df1.columns = ['A', 'B', 'C', 'V']
这就给了我们
A B C V
0 ABC USD 2.31 1.283
1 DEF MXN 4.72 0.880
2 XYZ EUR 5.83 0.120
谢谢,这是一个很好的解决方案!这个时候对我有用。唯一的问题是,如果列C也是一个浮点数,那么它将不起作用。10.1、10.2等。只需将列
C
乘以10(或任何数字),转换为int
,并使用完全相同的代码,只要将ceil
和floor
函数四舍五入到适当的间隔即可。这是我目前的方法-ccy\u dict={ccy:interp1d(df['C',df['V'],bounds\u error=False,fill\u value=(df['V'].iloc[0],df['V'].iloc[-1]),对于ccy,在ccy\u\u df.groupby('B')}
后面是-df1['V']=df1.apply(λx:ccy dict[x['B']](x['C']),axis=1)