Pandas 在每行给定值的不同数据帧之间进行线性插值

Pandas linear interpolate between different dataframes given values in each row

我们有几个不同国家(比如中国、美国、印度等)根据期限的苹果价格数据框,如下所示。 以中国为例:

tenors = pd.Series(['1W', '1M', '1Y'])
apples_china = pd.Series([5.1, 6.2, 7.1])
days = pd.Series([7, 30, 365])
data = {'tenors': tenors, 
   'apples_china':  apples_china,
   'days' : days}
apples_china = pd.DataFrame(data)

然后我们将为美国 (apples_usa)、欧洲 (apples_eu) 等提供等效的

然后我们有一个更大的 'portfolio' 数据框,如下所示:

country = pd.Series(['china', 'usa', 'europe',' china', 'china', 'india'])
days = pd.Series([12, 45, 99, 101, 102, 300 ])
portfolio = {'country': country, 
   'days' : days}
df_portfolio = pd.DataFrame(portfolio)

我想添加一列:

df_portfolio['price']

查看 df_portfolio['country'] 中的值,例如,如果它是 'china',则取天数(第 [0] 行中的 12)和在 apples_china 数据帧内线性插值。因此,行[0]上的值介于 5.1 和 6.2 之间,行[3] 上的值介于 6.2 和 7.1 之间,依此类推。

对于第 [1] 行,它将在类似的 apples_usa 数据框等内部查看

我试过的是:

from scipy.interpolate import interp1d
test = interp1d(apples_china['apples_china'], apples_china['days']) #arrays Y and X 
df_portfolio['price'] = np.where(df_portfolio['country']=='china', test(df_portfolio['days']), 0)

但它返回了 ValueError 和 x 范围。

有几个选项的解决方案适合numpy.where处理。

但是,对于涉及多个国家/地区的可扩展解决方案,字典可能更有用。下面我列出了必要的步骤:

步骤 1

创建一个将国家/地区映射到您的国家/地区特定数据的字典。

country_map = {'china': apples_china.sort_values('days')}

请注意,我们需要确保您的国家/地区数据框按 days 排序,以确保第 2 步中的 np.interp 按要求工作。

步骤 2

定义一个自定义函数,它从您的投资组合数据框中获取一行数据,以及第 1 步中的映射字典,然后使用 np.interp 执行映射。您可以使用 try / except 子句来捕获字典中不存在国家/地区的实例。

def interpolator(row, mapper):
    days = row['days']
    country = row['country']
    try:
        return np.interp(days, mapper[country]['days'].values,
                         mapper[country]['apples_china'].values)
    except KeyError:
        return np.nan

步骤 3

使用pd.DataFrame.apply逐行应用步骤 2 中的函数。

df_portfolio['price'] = df_portfolio.apply(interpolator, mapper=country_map, axis=1)

结果

print(df_portfolio)

  country  days     price
0   china    12  5.339130
1     usa    45       NaN
2  europe    99       NaN
3   china   101  6.390746
4   china   102  6.393433
5   india   300       NaN