将新列作为增量计算为pandas数据框中的另一个值

时间:2019-04-24 16:56:53

标签: python pandas

我有这个数据框:

     rank  cost brand city
0     1     1     a    x
1     2     2     a    x
2     3     3     a    x
3     4     4     a    x
4     5     5     a    x
5     1     2     b    y
6     2     4     b    y
7     3     6     b    y
8     4     8     b    y
9     5    10     b    y

我想创建一个新的列“ delta”,其中包含与某些品牌城市组合的排名1相比的成本差异。

所需结果:

     rank  cost brand city delta
0     1     1     a    x     0
1     2     2     a    x     1
2     3     3     a    x     2
3     4     4     a    x     3
4     5     5     a    x     4
5     1     2     b    y     0
6     2     4     b    y     2
7     3     6     b    y     4
8     4     8     b    y     6
9     5    10     b    y     8

This answer给了我一些提示,但是我坚持不能将序列映射到多索引这一事实。

为节省输入时间,以下是一些代码:

data = {'rank': [1, 2, 3, 4, 5, 1, 2, 3, 4, 5], 
     'cost': [1, 2, 3, 4, 5, 2, 4, 6, 8, 10],
     'brand': ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b'],
     'city': ['x', 'x', 'x', 'x', 'x', 'y', 'y', 'y', 'y', 'y'],
     'delta': ['0', '1', '2', '3', '4', '0', '2', '4', '6', '8']
     }

3 个答案:

答案 0 :(得分:4)

这是first + df['delta']=df.cost-df.groupby(['brand','city'])['cost'].transform('first') df Out[291]: rank cost brand city delta 0 1 1 a x 0 1 2 2 a x 1 2 3 3 a x 2 3 4 4 a x 3 4 5 5 a x 4 5 1 2 b y 0 6 2 4 b y 2 7 3 6 b y 4 8 4 8 b y 6 9 5 10 b y 8

{{1}}

答案 1 :(得分:1)

groupbyapply一起使用

data['delta'] = (data.groupby(['brand', 'city'], group_keys=False)
                     .apply(lambda x: x['cost'] - x[x['rank'].eq(1)]['cost'].values[0]))

data

   rank  cost brand city delta
0     1     1     a    x     0
1     2     2     a    x     1
2     3     3     a    x     2
3     4     4     a    x     3
4     5     5     a    x     4
5     1     2     b    y     0
6     2     4     b    y     2
7     3     6     b    y     4
8     4     8     b    y     6
9     5    10     b    y     8

答案 2 :(得分:1)

解决方案,不使用groupby。它对rank进行排序,并使用pd.merge_orderedassign创建delta

In [1077]: pd.merge_ordered(data.sort_values(['brand', 'city', 'rank']), data.query('rank == 1'), how='left', on=['brand', 'city', 'rank'], fill_method='ffill').assign(delta=lambda x: x.cost_x - x.cost_y).drop('cost_y', 1)
Out[1077]:
  brand city  cost_x  rank  delta
0     a    x       1     1      0
1     a    x       2     2      1
2     a    x       3     3      2
3     a    x       4     4      3
4     a    x       5     5      4
5     b    y       2     1      0
6     b    y       4     2      2
7     b    y       6     3      4
8     b    y       8     4      6
9     b    y      10     5      8