Pandas dataframe 将满足两个不同要求的两行相加

Pandas dataframe sum two rows if they meet two different requirements

我有以下table。

| product | check | check1 | type | amount |
|---------|-------|--------|------|--------|
| A       | 1     | a      | c    | -10    |
| A       | 1     | a      | p    | 20     |
| B       | 2     | b      | c    | 20     |
| B       | 2     | b      | p    | 20     |
| C       | 3     | c      | c    | -10    |
| D       | 4     | d      | p    | 15     |
| D       | 4     | d      | c    | -15    |

我想对前三列相等且 'type' 列中的一行包含 'C' 而另一行包含 'P' 的行求和,然后也其中 'type' = 'C' 金额应为负数,而当 'type' = 'P' 金额应为正数,否则不应相加。如果将它们相加,如果 'amount' 为负数,则 'type' 应为 'c',否则为 'p'。请参阅下面的所需输出:

| product | check | check1 | type | amount |
|---------|-------|--------|------|--------|
| A       | 1     | a      | p    | 10     |
| B       | 2     | b      | c    | 20     |
| B       | 2     | b      | p    | 20     |
| C       | 3     | c      | c    | -10    |
| D       | 4     | d      | p    | 0      |

我已经尝试 group.by 前三列,然后应用 lambda 函数;

df = df.groupby(['product', 'check', 'check1']).apply(lambda x, y : x + y, x.loc[(x['type']=='c')], y.loc[(y['type']=='p')], 'amount')

这给出了一个 NameError,其中 'x' 未定义。我也不确定这是否是正确的方法,所以如果您有任何提示,请告诉我!

这里有一个解决方案,可能效率不高,但很管用!

new_df = pd.DataFrame()
for product in df['product'].unique():
    for check in df[df['product'] == product].check.unique():
        for check1 in df[(df['product'] == product) & (df.check == check)].check1.unique():
            tmp = df[(df['product'] == product) & (df.check == check) & (df.check1 == check1)]
            if len(tmp[((tmp.type == 'c') & (tmp.amount < 0)) | ((tmp.type == 'p') & (tmp.amount > 0))]) != 2:
                new_df = new_df.append(tmp, ignore_index=True)
            else:
                amount = tmp.sum()['amount']
                type = 'c' if amount < 0 else 'p'                
                elt = {
                    'product': product,
                    'check': check,
                    'check1': check1,
                    'type': type,
                    'amount': amount
                }
                new_df = new_df.append(pd.Series(elt), ignore_index=True)