首页 > 解决方案 > concat + groupby + 在熊猫数据框中的多列中应用

问题描述

我有以下两个数据框:

df1

ticker       date       return      high_low      turnover
CRM         2017-01-03  0.018040    0.026957    5.722346e+08
MSFT        2017-01-03  -0.003344   0.011428    1.295037e+09
CRM         2017-01-04  0.024198    0.032646    6.762756e+08
MSFT        2017-01-04  -0.002881   0.010142    1.329482e+09
CRM         2017-01-05  -0.000275   0.015580    3.417927e+08

df2:

ticker       date       return      high_low    turnover
CRM         2017-01-03  0.018040    0.026957    5.722318e+08
MSFT        2017-01-03  -0.003344   0.011509    1.295037e+09
CRM         2017-01-04  0.024198    0.032575    6.761264e+08
MSFT        2017-01-04  -0.002881   0.010142    1.329480e+09
CRM         2017-01-05  -0.000275   0.015580    3.417930e+08

我有以下代码工作。但我想可以将最后四行简化为一行。仅在一行中执行三列的 concat+groupby+apply。

def get_min_absvalue(values):
    return min(values, key = abs)

#simplify the following 4 lines in 1?
consolidated_return=(pd.concat((df1,df2),ignore_index=True,sort=False).groupby(['date','ticker'])['return'].apply(lambda x: get_min_absvalue(x)).reset_index())
consolidated_high_low=(pd.concat((df1,df2),ignore_index=True,sort=False).groupby(['date','ticker'])['high_low'].apply(lambda x: get_min_absvalue(x)).reset_index())
consolidated_turnover=(pd.concat((df1,df2),ignore_index=True,sort=False).groupby(['date','ticker'])['turnover'].apply(lambda x: get_min_absvalue(x)).reset_index())

merged = consolidated_return.merge(consolidated_high_low, on=['date', 'ticker']).merge(consolidated_turnover, on=['date', 'ticker'])

那可能吗?

标签: pythonpython-3.xpandasgroup-byconcat

解决方案


来自df1&的列df2

  • 创建一个list列名
used_cols = ['return', 'high_low', 'turnover']

数据框列表:

  • 使用列表推导创建 DataFrame 列表
df_list = [pd.concat((df1, df2), ignore_index=True, sort=False).groupby(['date', 'ticker'])[v].apply(lambda x: min(x, key=abs)) for v in used_cols]

内容df_list

  • 这些是类型pandas.core.series.Series
df_list[0]

date        ticker
2017-01-03  CRM       0.026957
            MSFT      0.011428
2017-01-04  CRM       0.032575
            MSFT      0.010142
2017-01-05  CRM       0.015580
Name: high_low, dtype: float64

使用concat代替merge

  • 轻松df_list结合concat
merged = pd.concat(df_list, axis=1).reset_index()

最终数据框:

在此处输入图像描述

比较使用新代码和原始代码创建的 DataFrame:

merged_new == merged_old

在此处输入图像描述

最终代码:

  • 与 6 行代码相比,只有 3 行代码,并且没有重复。
used_cols = ['return', 'high_low', 'turnover']
df_list = [pd.concat((df1, df2), ignore_index=True, sort=False).groupby(['date', 'ticker'])[v].apply(lambda x: min(x, key=abs)) for v in used_cols]
merged = pd.concat(df_list, axis=1).reset_index()

推荐阅读