【问题标题】:concat + groupby + apply in multiple columns in panda dataframeconcat + group by + 在 pandas 数据框中的多列中应用
【发布时间】:2019-09-02 18:35:51
【问题描述】:

我有以下两个数据框:

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'])

这可能吗?

【问题讨论】:

    标签: python python-3.x pandas group-by concat


    【解决方案1】:

    来自df1df2 的列:

    • 创建一个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_listconcat
    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()
    

    【讨论】:

      【解决方案2】:

      考虑一个简单的min 聚合调用:

      agg_df = (pd.concat([df1,df2], ignore_index=True, sort=False)
                    .groupby(['date','ticker'], as_index=False)
                    .min()
               )
      
      print(agg_df)
      #         date ticker    return  high_low      turnover
      # 0 2017-01-03    CRM  0.018040  0.026957  5.722318e+08
      # 1 2017-01-03   MSFT -0.003344  0.011428  1.295037e+09
      # 2 2017-01-04    CRM  0.024198  0.032575  6.761264e+08
      # 3 2017-01-04   MSFT -0.002881  0.010142  1.329480e+09
      # 4 2017-01-05    CRM -0.000275  0.015580  3.417927e+08
      
      print(merged.eq(agg_df))
      #    date  ticker  return  high_low  turnover
      # 0  True    True    True      True      True
      # 1  True    True    True      True      True
      # 2  True    True    True      True      True
      # 3  True    True    True      True      True
      # 4  True    True    True      True      True
      

      对于真正的绝对值最小聚合:

      agg_df = (pd.concat([df1,df2], ignore_index=True, sort=False)
                    .groupby(['date','ticker'], as_index=False)['return', 'high_low', 'turnover']
                    .apply(lambda x: x.abs().min())
                    .reset_index()
                  )
      
      print(agg_df)
      
      #         date ticker    return  high_low      turnover
      # 0 2017-01-03    CRM  0.018040  0.026957  5.722318e+08
      # 1 2017-01-03   MSFT  0.003344  0.011428  1.295037e+09
      # 2 2017-01-04    CRM  0.024198  0.032575  6.761264e+08
      # 3 2017-01-04   MSFT  0.002881  0.010142  1.329480e+09
      # 4 2017-01-05    CRM  0.000275  0.015580  3.417927e+08
      

      【讨论】:

        猜你喜欢
        • 2014-04-08
        • 2015-03-07
        • 1970-01-01
        • 1970-01-01
        • 2016-12-31
        • 2021-12-06
        • 1970-01-01
        • 2017-11-15
        • 2018-01-25
        相关资源
        最近更新 更多