<p>我尝试用<code>periods</code>创建更通用的解决方案:</p>
<pre><code>print (df)
email user_name sessions ymo
0 a@a.com JD 1 2015-03-01
1 a@a.com JD 2 2015-05-01
2 b@b.com AB 1 2015-03-01
3 b@b.com AB 2 2015-05-01
mbeg = pd.period_range('2015-01', periods=12, freq='M')
print (mbeg)
PeriodIndex(['2015-01', '2015-02', '2015-03', '2015-04', '2015-05', '2015-06',
'2015-07', '2015-08', '2015-09', '2015-10', '2015-11', '2015-12'],
dtype='int64', freq='M')
#convert column ymo to period
df.ymo = df.ymo.dt.to_period('m')
#groupby and reindex with filling 0
df = df.groupby(['email','user_name'])
.apply(lambda x: x.set_index('ymo')
.reindex(mbeg, fill_value=0)
.drop(['email','user_name'], axis=1))
.rename_axis(('email','user_name','ymo'))
.reset_index()
</code></pre>
<pre><code>print (df)
email user_name ymo sessions
0 a@a.com JD 2015-01 0
1 a@a.com JD 2015-02 0
2 a@a.com JD 2015-03 1
3 a@a.com JD 2015-04 0
4 a@a.com JD 2015-05 2
5 a@a.com JD 2015-06 0
6 a@a.com JD 2015-07 0
7 a@a.com JD 2015-08 0
8 a@a.com JD 2015-09 0
9 a@a.com JD 2015-10 0
10 a@a.com JD 2015-11 0
11 a@a.com JD 2015-12 0
12 b@b.com AB 2015-01 0
13 b@b.com AB 2015-02 0
14 b@b.com AB 2015-03 1
15 b@b.com AB 2015-04 0
16 b@b.com AB 2015-05 2
17 b@b.com AB 2015-06 0
18 b@b.com AB 2015-07 0
19 b@b.com AB 2015-08 0
20 b@b.com AB 2015-09 0
21 b@b.com AB 2015-10 0
22 b@b.com AB 2015-11 0
23 b@b.com AB 2015-12 0
</code></pre>
<p>如果需要<code>datetimes</code>使用<a href="http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_timestamp.html" rel="nofollow">^{<cd3>}</a>:</p>
<pre><code>df.ymo = df.ymo.dt.to_timestamp()
print (df)
email user_name ymo sessions
0 a@a.com JD 2015-01-01 0
1 a@a.com JD 2015-02-01 0
2 a@a.com JD 2015-03-01 1
3 a@a.com JD 2015-04-01 0
4 a@a.com JD 2015-05-01 2
5 a@a.com JD 2015-06-01 0
6 a@a.com JD 2015-07-01 0
7 a@a.com JD 2015-08-01 0
8 a@a.com JD 2015-09-01 0
9 a@a.com JD 2015-10-01 0
10 a@a.com JD 2015-11-01 0
11 a@a.com JD 2015-12-01 0
12 b@b.com AB 2015-01-01 0
13 b@b.com AB 2015-02-01 0
14 b@b.com AB 2015-03-01 1
15 b@b.com AB 2015-04-01 0
16 b@b.com AB 2015-05-01 2
17 b@b.com AB 2015-06-01 0
18 b@b.com AB 2015-07-01 0
19 b@b.com AB 2015-08-01 0
20 b@b.com AB 2015-09-01 0
21 b@b.com AB 2015-10-01 0
22 b@b.com AB 2015-11-01 0
23 b@b.com AB 2015-12-01 0
</code></pre>
<p>带日期时间的解决方案:</p>
<pre><code>print (df)
email user_name sessions ymo
0 a@a.com JD 1 2015-03-01
1 a@a.com JD 2 2015-05-01
2 b@b.com AB 1 2015-03-01
3 b@b.com AB 2 2015-05-01
mbeg = pd.date_range('2015-01-31', periods=12, freq='M') - pd.offsets.MonthBegin()
df = df.groupby(['email','user_name'])
.apply(lambda x: x.set_index('ymo')
.reindex(mbeg, fill_value=0)
.drop(['email','user_name'], axis=1))
.rename_axis(('email','user_name','ymo'))
.reset_index()
</code></pre>
<pre><code>print (df)
email user_name ymo sessions
0 a@a.com JD 2015-01-01 0
1 a@a.com JD 2015-02-01 0
2 a@a.com JD 2015-03-01 1
3 a@a.com JD 2015-04-01 0
4 a@a.com JD 2015-05-01 2
5 a@a.com JD 2015-06-01 0
6 a@a.com JD 2015-07-01 0
7 a@a.com JD 2015-08-01 0
8 a@a.com JD 2015-09-01 0
9 a@a.com JD 2015-10-01 0
10 a@a.com JD 2015-11-01 0
11 a@a.com JD 2015-12-01 0
12 b@b.com AB 2015-01-01 0
13 b@b.com AB 2015-02-01 0
14 b@b.com AB 2015-03-01 1
15 b@b.com AB 2015-04-01 0
16 b@b.com AB 2015-05-01 2
17 b@b.com AB 2015-06-01 0
18 b@b.com AB 2015-07-01 0
19 b@b.com AB 2015-08-01 0
20 b@b.com AB 2015-09-01 0
21 b@b.com AB 2015-10-01 0
22 b@b.com AB 2015-11-01 0
23 b@b.com AB 2015-12-01 0
</code></pre>