匹配最接近的值面板数据 Pandas

Matching closest values panel data Pandas

我目前正在做一个涉及财务数据的项目。我有一个数据框,其中包含许多基本变量以及许多不同公司的股票 returns,就像这样:

           year     ticker      tot_assets      return
0          1999       AAPL          10.345      0.1294
1          2000       AAPL          10.988      0.1577
2          2001       AAPL          12.003      0.0782
..          ...        ...             ...         ...
34521      2017       GMBO           0.893      0.2209
34522      2018       GMBO           1.206      0.1001
..          ...        ...             ...         ...
200344     2012         ZZ           3.789      0.0032
200344     2013         ZZ           3.021     -0.0346

我一直试图做但没有成功的是,根据同一年最接近的 tot_assets 值,将每一年的每家公司 ticker 与 df 中的另一家公司相匹配.因此创建两个新列,其中一个包含匹配公司的 ticker 以及当年的 returns

所以它应该看起来像这样:

           year     ticker   tot_assets   return   m_ticker   m_return
0          1999       AAPL       10.345   0.1294         AA     0.0890
1          2000       AAPL       10.988   0.1577         AA     0.1666
2          2001       AAPL       12.003   0.0782       TSLA     0.3470
..          ...        ...          ...      ...        ...        ...
34521      2017       GMBO        0.893   0.2209        AIR     0.0032
34522      2018       GMBO        1.206   0.1001       CECE     0.1123
..          ...        ...          ...      ...        ...        ...
200344     2012         ZZ        3.789   0.0032       ASKI     0.0432
200344     2013         ZZ        3.021  -0.0346       ASKI     0.0339

我希望我的解释足够清楚 :P 也许这就是我遇到麻烦的原因!我无法向您展示 df,因为它有更多 200'000 个观察结果 - 但我希望上述概念对您有所帮助 :)

提前致谢!

merge 年内并删除任何与自身合并的代码。然后确定'total_assets'中的绝对差。通过排序和删除重复项,我们只保留原始 DataFrame 中每个 ['ticker'、'year'] 的最接近匹配项。

示例数据

           year     ticker      tot_assets      return
0          1999       AAPL          10.345      0.1294
1          2000       AAPL          10.988      0.1577
34521      1999       GMBO           0.893      0.2209
34522      2000       GMBO           1.206      0.1001
200344     1999         ZZ           3.789      0.0032
200344     2000         ZZ           3.021     -0.0346

代码

df = df.merge(df, on='year', suffixes=['', '_closest']).query('ticker != ticker_closest')
df['diff'] = (df['tot_assets'] - df['tot_assets_closest']).abs()
df = df.sort_values('diff').drop_duplicates(['year', 'ticker'])

输出:

    year ticker  tot_assets  return ticker_closest  tot_assets_closest  return_closest   diff
14  2000   GMBO       1.206  0.1001             ZZ               3.021         -0.0346  1.815
16  2000     ZZ       3.021 -0.0346           GMBO               1.206          0.1001  1.815
5   1999   GMBO       0.893  0.2209             ZZ               3.789          0.0032  2.896
7   1999     ZZ       3.789  0.0032           GMBO               0.893          0.2209  2.896
2   1999   AAPL      10.345  0.1294             ZZ               3.789          0.0032  6.556
11  2000   AAPL      10.988  0.1577             ZZ               3.021         -0.0346  7.967

以上将是一个非常大的合并。另一种选择是使用 pd.merge_asofallow_exact_matches=False。因为 tot_assets 是一个浮点数,所以两个不同的代码不太可能具有完全相同的值,所以 allow_exact_matches=False 从本质上防止了相同的代码与自身合并。但是,如果有另一个代码完全相同 tot_assets,我们将使用此方法错过它。

df = df.sort_values('tot_assets')
df = (pd.merge_asof(df, df.add_suffix('_closest'), 
                    left_by='year', right_by='year_closest',
                    left_on='tot_assets', right_on='tot_assets_closest',
                    direction='nearest',
                    allow_exact_matches=False)
        .drop(columns='year_closest'))