【问题标题】:Retain the highest absolute value and return an average value from rows with duplicate index保留最高绝对值并从具有重复索引的行中返回平均值
【发布时间】:2018-12-09 01:19:10
【问题描述】:

我在 DataFrame 中有一组具有重复索引的值:

         value
CDE   2.318620
CDE  -3.097715
LXU  -3.791043
LXU   4.818995
SWN   3.059964
SWN  -4.349304
OAS  -3.336539
LPI  -3.037097
LPI  -5.701044
LPI  -3.519923
CZR  -3.270018
CZR  -3.056712

要求的结果是只保留最高的绝对值并在新列中返回平均值:

         value    average
CDE  -3.097715  -0.389547
LXU   4.818995   0.513976
SWN  -4.349304  -0.644670
OAS  -3.336539  -3.336539
LPI  -5.701044  -4.086021
CZR  -3.270018  -3.163365

我尝试将 .apply(lambda) 应用于重复的行,但出现“轴”错误:

max_absolute = lambda x: max(x.min(), x.max(), key=abs)
df_duplicate_absmax = df.groupby(df.index).apply(max_absolute, axis=1)

ps:调整 Abhi 的解决方案以使用 NaN:

df1 = df.groupby(df.index)['value'].agg([lambda x: max(x[~np.isnan(x)], key=abs), 'mean'])

【问题讨论】:

    标签: python python-3.x pandas dataframe pandas-groupby


    【解决方案1】:

    用途:

    df1 = df.groupby(df.index)['value'].agg([lambda x: max(x,key=abs), 'mean'])
    
    df1.columns = ['value', 'average']
    
    print (df1)
    
            value   average
    CDE -3.097715 -0.389547
    CZR -3.270018 -3.163365
    LPI -5.701044 -4.086021
    LXU  4.818995  0.513976
    OAS -3.336539 -3.336539
    SWN -4.349304 -0.644670
    

    【讨论】:

    • 此解决方案效率低下的原因有两个:(1)在 Pandas 系列/NumPy 数组中使用纯 Python 内置函数(max),(2)单次使用 groupby 两次groupby 就足够了。
    • 很好的解决方案,Abhi 非常感谢 :) 为了简单起见,我很欣赏使用 max_absolute lambda 函数!
    • 不错!请注意,列可以直接在 .agg 中命名,例如 .agg([('value', lambda x: max(x,key=abs)), ('average', 'mean')])
    • 非常棒,Andrew Lavers 为一个好的解决方案增加了价值!谢谢:)
    【解决方案2】:

    这是一个使用groupby + agg 的解决方案,它有两个函数,一个是通过绝对值计算最大值,另一个是计算平均值:

    def max_abs(x):
        return x.iloc[x.abs().values.argmax()]
    
    res = df.groupby(level=0).agg([max_abs, 'mean'])\
            .xs('value', axis=1, drop_level=True)
    
    print(res)
    
          max_abs      mean
    CDE -3.097715 -0.389547
    CZR -3.270018 -3.163365
    LPI -5.701044 -4.086021
    LXU  4.818995  0.513976
    OAS -3.336539 -3.336539
    SWN -4.349304 -0.644670
    

    【讨论】:

    • 太棒了,jpp - 非常 Pythonic!
    • 我也喜欢你使用 .xs() 和 MultiIndex 地址,jpp :)
    【解决方案3】:
    from io import StringIO
    import pandas as pd
    df = pd.read_fwf(StringIO("""
    cod      value
    CDE   2.318620
    CDE  -3.097715
    LXU  -3.791043
    LXU   4.818995
    SWN   3.059964
    SWN  -4.349304
    OAS  -3.336539
    LPI  -3.037097
    LPI  -5.701044
    LPI  -3.519923
    CZR  -3.270018
    CZR  -3.056712
    """), header=1, Index=None)
    
    # Create a new column with absoulte value
    df['abs_value'] = df['value'].abs()
    
    # Calulate the mean in new data farame, grouped by code using
    # pandas groupped aggregation naming the column average
    df_avg = df.groupby("cod").value.agg([('average', 'mean')])
    
    # Choose the row within group with largest abs value
    df_abs = df.sort_values("abs_value").groupby("cod").tail(1)[["cod", "value"]]
    
    # Join the average and the max
    df_abs.join(df_avg, on="cod")
    

    结果:

        cod     value   average
    1   CDE -3.097715 -0.389547
    10  CZR -3.270018 -3.163365
    6   OAS -3.336539 -3.336539
    5   SWN -4.349304 -0.644670
    3   LXU  4.818995  0.513976
    8   LPI -5.701044 -4.086021
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-30
      • 2014-03-29
      • 2012-09-30
      • 1970-01-01
      • 2013-07-10
      • 2021-08-10
      • 2021-07-13
      相关资源
      最近更新 更多