代码之家  ›  专栏  ›  技术社区  ›  jpp

按熊猫分组的条件偏移值

  •  7
  • jpp  · 技术社区  · 8 年前

    值始终为非负 Offset == False 总是消极的 Offset == True . 我要做的是按标签将正值(地板为0)与负值“折叠”。

    Label + Offset 抵消 是布尔值,每个标签最多只能有2行。

    df = pd.DataFrame({'Label': ['L1', 'L2', 'L3', 'L3'],
                       'Offset': [False, False, False, True],
                       'Value': [100, 100, 50, -100]})
    
    # input
    #   Label Offset  Value
    # 0    L1  False    100
    # 1    L2  False    100
    # 2    L3  False     50
    # 3    L3   True   -100
    

    期望输出:

      Label Offset  Value
    0    L1  False    100
    1    L2  False    100
    2    L3  False      0
    3    L3   True    -50
    

    例2

    df = pd.DataFrame({'Label': ['L1', 'L2', 'L3', 'L3'],
                       'Offset': [False, False, False, True],
                       'Value': [100, 100, 100, -50]})
    
    # input
    #   Label Offset  Value
    # 0    L1  False    100
    # 1    L2  False    100
    # 2    L3  False    100
    # 3    L3   True    -50
    

    期望输出:

      Label Offset  Value
    0    L1  False    100
    1    L2  False    100
    2    L3  False     50
    3    L3   True      0
    

    当前效率低下的解决方案

    我目前的解决方案是手动循环,速度慢且难以维护:

    for label in df['Label'].unique():
        mask = df['Label'] == label
        if len(df.loc[mask]) == 2:
            val_false = df.loc[~df['Offset'] & mask, 'Value'].iloc[0]
            val_true = df.loc[df['Offset'] & mask, 'Value'].iloc[0]
            if val_false > abs(val_true):
                df.loc[~df['Offset'] & mask, 'Value'] += val_true
                df.loc[df['Offset'] & mask, 'Value'] = 0
            else:
                df.loc[~df['Offset'] & mask, 'Value'] = 0
                df.loc[df['Offset'] & mask, 'Value'] += val_false
    

    我正在寻找一个矢量化,或至少部分矢量化的解决方案,以提高性能和摆脱这种混乱。

    3 回复  |  直到 8 年前
        1
  •  6
  •   DSM    8 年前

    也许 吧:

    label_sums = df.Value.groupby(df.Label).transform(sum)
    df["new_sum"] = label_sums.where(np.sign(label_sums) == np.sign(df.Value), 0)
    

    In [42]: df
    Out[42]: 
      Label  Offset  Value  new_sum
    0    L1   False    100      100
    1    L2   False    100      100
    2    L3   False     50        0
    3    L3    True   -100      -50
    4    L4   False    100      100
    5    L5   False    100      100
    6    L6   False    100       50
    7    L6    True    -50        0
    
        2
  •  4
  •   Yuca    8 年前

    这是我得到的最好的结果:创建一个辅助列以找到显示聚合的位置,然后将组的其他成员设置为0

    df['aux'] = abs(df['Value'])
    idx = abs(df.groupby(['Label'])['aux'].transform(max)) == abs(df['aux'])
    df['aux2'] = False
    df.loc[idx,'aux2'] = True
    df  = df.join(df.groupby('Label').Value.sum(), on='Label', rsuffix = 'jpp')
    df.loc[df['aux2']==False, 'Valuejpp'] = 0
    df = df.drop(['aux', 'aux2','Value'], axis = 1)
    

    结果

          Label  Offset  Valuejpp
    0    L1   False       100
    1    L2   False       100
    2    L3   False         0
    3    L3    True       -50
    
        3
  •  4
  •   BENY    8 年前

    来自DSM的数据

    df1=df.copy()
    
    df.loc[df.Offset,'Value']=df.Value.abs()
    
    s1=(df.groupby('Label').Value.diff().lt(0)).groupby(df['Label']).transform('any')
    s2=df.groupby('Label').Value.transform('count')
    
    s3=df1.groupby('Label').Value.transform('sum')
    np.where(s2<=1,df1.Value,np.where(s1,s3*(-df1.Offset),s3*df1.Offset))
    
    Out[757]: array([100, 100,   0, -50, 100, 100,  50,   0], dtype=int64)