我试图根据一个datetime列按日期对Pandas数据帧进行分组,并据此基于一个特定值计算另一列中特定事件的发生次数。假设我有这个数据框:
df = pd.DataFrame({
"customer": [
"A", "A", "A", "A", "A", "B", "C", "C"
],
"datetime": pd.to_datetime([
"2020-01-01 00:00:00", "2020-01-02 00:00:00", "2020-01-02 01:00:00", "2020-01-03 00:00:00", "2020-01-04 00:00:00", "2020-01-03 00:00:00", "2020-01-03 00:00:00", "2020-01-04 00:00:00"
]),
"enabled": [
True, True, False, True, True, True, False, True
]
})
数据框如下所示:
customer datetime enabled
A 2020-01-01 00:00:00 True
A 2020-01-02 00:00:00 True
A 2020-01-02 01:00:00 False
A 2020-01-03 00:00:00 True
A 2020-01-04 00:00:00 True
B 2020-01-03 00:00:00 True
C 2020-01-03 00:00:00 False
C 2020-01-04 00:00:00 True
我想在每天结束时计算已启用客户的数量。如果启用了客户,则除非客户隔天有enabled==False
行,否则它将在接下来的几天保持启用状态。预期的输出将是:
day count_enabled_customers
2020-01-01 1 # A
2020-01-02 0 # A has been disabled
2020-01-03 2 # A, B
2020-01-04 3 # A, B, C
有人对如何进行此操作有想法吗?提前非常感谢!
答案 0 :(得分:6)
从数据框开始:
import pandas as pd
df = pd.DataFrame({
"customer": [
"A", "A", "A", "A", "A", "B", "C", "C"
],
"datetime": pd.to_datetime([
"2020-01-01 00:00:00", "2020-01-02 00:00:00", "2020-01-02 01:00:00", "2020-01-03 00:00:00", "2020-01-04 00:00:00", "2020-01-03 00:00:00", "2020-01-03 00:00:00", "2020-01-04 00:00:00"
]),
"enabled": [
True, True, False, True, True, True, False, True
]
})
print(df)
Out:
customer datetime enabled
0 A 2020-01-01 00:00:00 True
1 A 2020-01-02 00:00:00 True
2 A 2020-01-02 01:00:00 False
3 A 2020-01-03 00:00:00 True
4 A 2020-01-04 00:00:00 True
5 B 2020-01-03 00:00:00 True
6 C 2020-01-03 00:00:00 False
7 C 2020-01-04 00:00:00 True
使用数据透视表将客户作为列,将日期作为索引
a = df.pivot(index='datetime', columns='customer', values='enabled')
print(a)
Out:
customer A B C
datetime
2020-01-01 00:00:00 True NaN NaN
2020-01-02 00:00:00 True NaN NaN
2020-01-02 01:00:00 False NaN NaN
2020-01-03 00:00:00 True True False
2020-01-04 00:00:00 True NaN True
创建您感兴趣的日期的索引
dates = pd.date_range(df.datetime.min().date(), df.datetime.max().date() + pd.offsets.Day(1), freq='D') - pd.offsets.Second(1)
print(dates)
Out:
DatetimeIndex(['2019-12-31 23:59:59', '2020-01-01 23:59:59',
'2020-01-02 23:59:59', '2020-01-03 23:59:59',
'2020-01-04 23:59:59'],
dtype='datetime64[ns]', freq='D')
将您感兴趣的日期添加到索引中并对其进行排序,以便我们进行下一步
a = a.reindex(a.index.union(dates)).sort_index()
print(a)
Out:
customer A B C
2019-12-31 23:59:59 NaN NaN NaN
2020-01-01 00:00:00 True NaN NaN
2020-01-01 23:59:59 NaN NaN NaN
2020-01-02 00:00:00 True NaN NaN
2020-01-02 01:00:00 False NaN NaN
2020-01-02 23:59:59 NaN NaN NaN
2020-01-03 00:00:00 True True False
2020-01-03 23:59:59 NaN NaN NaN
2020-01-04 00:00:00 True NaN True
2020-01-04 23:59:59 NaN NaN NaN
将启用状态的最后一个值向前填充到将来的日期
a = a.ffill()
print(a)
Out:
customer A B C
2019-12-31 23:59:59 NaN NaN NaN
2020-01-01 00:00:00 True NaN NaN
2020-01-01 23:59:59 True NaN NaN
2020-01-02 00:00:00 True NaN NaN
2020-01-02 01:00:00 False NaN NaN
2020-01-02 23:59:59 False NaN NaN
2020-01-03 00:00:00 True True False
2020-01-03 23:59:59 True True False
2020-01-04 00:00:00 True True True
2020-01-04 23:59:59 True True True
列的总和,代表每天的结束时间
a.loc[dates].sum(axis=1)
print(a)
Out:
2019-12-31 23:59:59 0.0
2020-01-01 23:59:59 1.0
2020-01-02 23:59:59 0.0
2020-01-03 23:59:59 2.0
2020-01-04 23:59:59 3.0
Freq: D, dtype: float64