我想计算每封受尊重的电子邮件的不重复组合年月数
test_df = pd.DataFrame(
data={'email': ['a', 'a', 'b', 'b', 'c', 'c', 'c'],
'purchases': ['2016-08-25 01:09:42',
'2016-08-23 13:30:20',
'2018-10-23 05:33:15',
'2016-09-20 17:41:04',
'2017-04-09 17:59:00',
'2018-02-25 15:14:53',
'2016-02-25 15:14:53']})
test_df['purchases'] = pd.to_datetime(test_df['purchases'], yearfirst=True)
此后,我有了这个purchases
作为时间戳的DF
email purchases
0 a 2016-08-25 01:09:42
1 a 2016-08-23 13:30:20
2 b 2018-10-23 05:33:15
3 b 2016-09-20 17:41:04
4 c 2017-04-09 17:59:00
5 c 2018-02-25 15:14:53
6 c 2016-02-25 15:14:53
此后,我计算月份数并将值分配给新列months_of_active
:
test_df['months_of_active'] =
pd.DatetimeIndex(test_df.purchases).to_period("M").nunique()
哪个创建下一个输出:
email purchases months_of_active
0 a 2016-08-25 01:09:42 6
1 a 2016-08-23 13:30:20 6
2 b 2018-10-23 05:33:15 6
3 b 2016-09-20 17:41:04 6
4 c 2017-04-09 17:59:00 6
5 c 2018-02-25 15:14:53 6
6 c 2016-02-25 15:14:53 6
所需的输出是:
email purchases months_of_active
0 a 2016-08-25 01:09:42 1
1 a 2016-08-23 13:30:20 1
2 b 2018-10-23 05:33:15 2
3 b 2016-09-20 17:41:04 2
4 c 2017-04-09 17:59:00 3
5 c 2018-02-25 15:14:53 3
6 c 2016-02-25 15:14:53 3
a
= 1,因为有两个相似的月份
b
= 2,因为有两个不同的月份
c
= 2,因为有两个不同的月份(2个相同月份,另一个1个月份)
无法理解,在上面的函数中添加了哪些内容以对过滤后的系列执行to_period()。
更新:
我确实也需要考虑年份,2017-1
和2018-1
将被计为2。
答案 0 :(得分:1)
您需要对“电子邮件”进行分组,并将transform
与nunique
结合使用,以将唯一计数广播到原始DataFrame的行中:
s = pd.Series(pd.DatetimeIndex(df.purchases).to_period('M'), index=df.index)
df['months_of_active'] = s.groupby(df.email).transform('nunique')
df
email purchases months_of_active
0 a 2016-08-25 01:09:42 1
1 a 2016-08-23 13:30:20 1
2 b 2018-10-23 05:33:15 2
3 b 2016-09-20 17:41:04 2
4 c 2017-04-09 17:59:00 3
5 c 2018-02-25 15:14:53 3
6 c 2016-02-25 15:14:53 3
或者,使用dt.strftime
获得“年-月”组合:
df['months_of_active'] = (
df.purchases.dt.strftime('%Y-%m').groupby(df.email).transform('nunique'))
df
email purchases months_of_active
0 a 2016-08-25 01:09:42 1
1 a 2016-08-23 13:30:20 1
2 b 2018-10-23 05:33:15 2
3 b 2016-09-20 17:41:04 2
4 c 2017-04-09 17:59:00 3
5 c 2018-02-25 15:14:53 3
6 c 2016-02-25 15:14:53 3
答案 1 :(得分:0)
为避免转换为年月字符串或object
dtype系列,您可以标准化datetime
系列的日期和时间部分,然后使用pd.Series.nunique
:
# convert purchases series to datetime
df['purchases'] = pd.to_datetime(df['purchases'])
# normalize day to 1 and zero time component
df['year_month'] = (df['purchases'] + pd.offsets.MonthBegin(1)).dt.normalize()
# calculate counts
email_counts = df.groupby('email')['year_month'].nunique()
# assign counts to series and drop helper series
df = df.assign(count=df['email'].map(email_counts)).drop('year_month', 1)
print(df)
email purchases count
0 a 2016-08-25 01:09:42 1
1 a 2016-08-23 13:30:20 1
2 b 2018-10-23 05:33:15 2
3 b 2016-09-20 17:41:04 2
4 c 2017-04-09 17:59:00 3
5 c 2018-02-25 15:14:53 3
6 c 2016-02-25 15:14:53 3