我在尝试向DataFrame
添加字段时遇到问题,该字段总计过去三个月(即不包括本月)。
我有一个DataFrame
,显示与channel_id
相关的月费:
+-------+---------+------------+----------+-------------------------+
| index | date | channel_id | fee | NEW COLUMN |
+-------+---------+------------+----------+-------------------------+
| 10 | 2018-03 | 22 | 24525.88 | (depends on rows above) |
| 11 | 2018-04 | 22 | 10493 | (depends on rows above) |
| 12 | 2018-05 | 22 | 12500 | (depends on rows above) |
| 13 | 2017-10 | 43 | 1000 | 0 |
| 14 | 2017-11 | 43 | 1000 | 0 |
| 15 | 2017-12 | 43 | 1000 | 0 |
| 16 | 2018-01 | 43 | 1000 | 3000 |
| 17 | 2018-02 | 43 | 1000 | 3000 |
| 18 | 2018-03 | 43 | 1000 | 3000 |
| 19 | 2018-04 | 43 | 1000 | 3000 |
| 20 | 2018-05 | 43 | 1000 | 3000 |
| 21 | 2017-10 | 58 | 1750 | 0 |
| 22 | 2017-11 | 58 | 1750 | 0 |
| 23 | 2017-12 | 58 | 3302.1 | 0 |
| .. | .. | .. | .. | .. |
+-------+---------+------------+----------+-------------------------+
对于每个channel_id,我想汇总最近3个月的费用。每个channel_id的前三个月(例如行索引4,5,6)应该为0,因为前几个月没有总和。
为了达到这个目的,我正在使用:
df.groupby(['channel_id']).rolling(3)[fee].sum().shift(1).sort_index(level=1).fillna(0)
这个主要是,但是对于一些 channel_ids的第一个实例,它会填充一个我无法绑定到任何东西的值......:
+---------+------------+----------+----------+----------+
| date | channel_id | fee | NEW_COL | Correct? |
+---------+------------+----------+----------+----------+
| 2018-03 | 22 | 24525.88 | 52572.85 | YES |
| 2018-04 | 22 | 10493 | 60211.76 | YES |
| 2018-05 | 22 | 12500 | 53933.88 | YES |
| 2017-10 | 43 | 1000 | 2400 | NO!!! |
| 2017-11 | 43 | 1000 | 0 | YES |
| 2017-12 | 43 | 1000 | 0 | YES |
| 2018-01 | 43 | 1000 | 3000 | YES |
| 2018-02 | 43 | 1000 | 3000 | YES |
| 2018-03 | 43 | 1000 | 3000 | YES |
| 2018-04 | 43 | 1000 | 3000 | YES |
| 2018-05 | 43 | 1000 | 3000 | YES |
| 2017-10 | 58 | 1750 | 0 | YES |
| 2017-11 | 58 | 1750 | 0 | YES |
| 2017-12 | 58 | 3302.1 | 0 | YES |
+---------+------------+----------+----------+----------+
我对df操作的理解有点粗略,但我对链的理解是:
df.groupby(['channel_id'])
:通过channel_id
.rolling(3)[fee].sum()
:对groupby dfs
.shift(1)
:将值向上移动1(因为我们不想要当前月份)
.sort_index(level=1)
:不确定这在上下文中是做什么的,但它是必需的......
.fillna(0)
:将NaNs填充为0,其中前3个月不可用。
我玩过不同的sort_index值(和shift),但无法理解这是如何处理错误的值。
答案 0 :(得分:4)
使用apply
df.groupby(['channel_id'])['fee'].apply(lambda x :x.rolling(3).sum().shift(1).fillna(0))
Out[319]:
0 0.0
1 0.0
2 0.0
3 0.0
4 0.0
5 0.0
6 3000.0
7 3000.0
8 3000.0
9 3000.0
10 3000.0
11 0.0
12 0.0
13 0.0
Name: fee, dtype: float64
答案 1 :(得分:1)
我认为需要DataFrameGroupBy.shift
:
df['new'] = (df.groupby(['channel_id']).rolling(3)['fee'].sum()
.groupby(level=0)
.shift(1)
.sort_index(level=1)
.fillna(0)
.reset_index(level=0, drop=True))
print (df)
date channel_id fee NEW COLUMN new
index
10 2018-03 22 24525.88 NaN 0.0
11 2018-04 22 10493.00 NaN 0.0
12 2018-05 22 12500.00 NaN 0.0
13 2017-10 43 1000.00 0.0 0.0
14 2017-11 43 1000.00 0.0 0.0
15 2017-12 43 1000.00 0.0 0.0
16 2018-01 43 1000.00 3000.0 3000.0
17 2018-02 43 1000.00 3000.0 3000.0
18 2018-03 43 1000.00 3000.0 3000.0
19 2018-04 43 1000.00 3000.0 3000.0
20 2018-05 43 1000.00 3000.0 3000.0
21 2017-10 58 1750.00 0.0 0.0
22 2017-11 58 1750.00 0.0 0.0
23 2017-12 58 3302.10 0.0 0.0
或者可以按4
滚动:
df['new'] = (df.groupby(['channel_id']).rolling(4)['fee'].sum()
.sort_index(level=1)
.fillna(0)
.reset_index(level=0, drop=True))