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)