我有一个数据帧:
import pandas as pd
df = pd.DataFrame({
'Customer' : ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B'],
'EventTime' : ['2019-06-03 09:51:05', '2019-06-03 09:55:07',
'2019-06-03 10:02:00', '2019-06-03 10:06:00',
'2019-06-03 10:07:00', '2019-06-03 10:20:00',
'2019-06-03 10:29:59', '2019-06-03 09:51:00',
'2019-06-03 09:52:00'],
'Status' : ['NotWorking', 'Working', 'NotWorking', 'Working', 'NotWorking',
'Working', 'Working', 'NotWorking', 'Working']
})
df
每条记录表示在EventTime发生的事件。 我必须找出每一个顾客在15分钟的时间间隔内处于每一个状态的时间。 听起来很复杂,不是吗?你知道吗
例如,对于2019-06-03 09:51:05的客户A,状态更改为NotWorking。 对于这一记录,15分钟的时间是2019-06-03 09:45:00-2019-06-03 09:59:59。你知道吗
对于没有以前记录的记录,以前的状态为“工作”。 因此,从2019-06-03 09:45:00到2019-06-03 09:51:05的15分钟间隔,我们有365秒处于工作状态。你知道吗
现在,从2019-06-03 09:51:05到同一客户的下一个记录2019-06-03 09:55:07,我们有242秒处于NotWorking状态。你知道吗
从2019-06-03 09:55:07到2019-06-03 09:59:59 15分钟结束,我们有292+1=293秒处于工作状态(仍在工作)。你知道吗
因此,从2019-06-03 09:45:00开始的客户A和15分钟的首次记录如下:
A 2019-06-03 09:45:00工作=365+293=658,不工作=242
现在我们还有15分钟的时间,从2019-06-03 10:00开始。 从2019-06-03 10:00:00到2019-06-03 10:02:00,有120秒处于工作状态。 从2019-06-03 10:02:00到2019-06-03 10:06:00,有240秒处于NotWorking状态。 从2019-06-03 10:06:00到2019-06-03 10:07:00,有60秒处于工作状态。 从2019-06-03 10:07:00到2019-06-03 10:14:59 15分钟结束,有479+1=480秒处于未工作状态。你知道吗
因此,2019-06-03 10:00:00的15分钟内,客户A的下一个记录是:
A 2019-06-03 10:00:00工作=120+60=180,不工作=240+480=720。你知道吗
输出应为
有可能用熊猫做这样的计算吗?你知道吗
敬礼。你知道吗
编辑:这应该是最终结果
我已经这样做了,但我认为可以用更好的方式来做。你知道吗
def start_of_15_min(event_datetime):
minute = event_datetime.minute
if minute >= 45:
new_minute=45
elif minute >= 30:
new_minute=30
elif minute >= 15:
new_minute=15
elif minute >= 0:
new_minute=0
new_event_datetime = datetime.datetime(event_datetime.year, event_datetime.month, event_datetime.day, event_datetime.hour, new_minute, 0)
return new_event_datetime
def end_of_15_min(event_datetime):
start_of_15_min_per = start_of_15_min(event_datetime)
return start_of_15_min_per + datetime.timedelta(seconds=899)
# In[308]:
df = pd.DataFrame({
'Customer' : ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B'],
'Status' : ['NotWorking', 'Working', 'NotWorking', 'Working', 'NotWorking',
'Working', 'Working', 'NotWorking', 'Working'],
'EventTime' : ['2019-06-03 09:51:05', '2019-06-03 09:55:07',
'2019-06-03 10:02:00', '2019-06-03 10:06:00',
'2019-06-03 10:07:00', '2019-06-03 10:20:00',
'2019-06-03 10:29:59', '2019-06-03 09:51:00',
'2019-06-03 09:52:00'],
})
df.EventTime = pd.to_datetime(df.EventTime)
df
# In[310]:
df.groupby('Customer').EventTime.agg(['min', 'max']).applymap(start_of_15_min)
# In[311]:
for idx, row in df.groupby('Customer').EventTime.agg(['min', 'max']).applymap(start_of_15_min).iterrows():
for event_time in pd.date_range(start=row['min'], end=row['max'], freq='15T'):
if len(df[(df.Customer == idx) & (df.EventTime == event_time)]) == 0:
new_row = pd.DataFrame({'Customer' : idx, 'Status': np.nan, 'EventTime' : event_time}, index=[0])
df = df.append(new_row)
df = df.sort_values(['Customer', 'EventTime']).reset_index(drop=True)
df
# In[313]:
df.Status = df.groupby('Customer').Status.fillna(df.groupby('Customer').Status.shift())
df
# In[314]:
df.Status = df.Status.fillna('Working')
df
# In[315]:
for idx, row in df.groupby('Customer').EventTime.agg(['min', 'max']).applymap(end_of_15_min).iterrows():
for event_time in pd.date_range(start=row['min'], end=row['max'], freq='15T'):
if len(df[(df.Customer == idx) & (df.EventTime == event_time)]) == 0:
new_row = pd.DataFrame({'Customer' : idx, 'Status': np.nan, 'EventTime' : event_time}, index=[0])
df = df.append(new_row)
df = df.sort_values(['Customer', 'EventTime']).reset_index(drop=True)
df
# In[316]:
df.Status = df.groupby('Customer').Status.fillna(df.groupby('Customer').Status.shift())
df
# In[317]:
df['Seconds'] = df.groupby('Customer').EventTime.apply(lambda x: (x.shift(-1) - x).dt.seconds)
df
# In[318]:
df['StartOf15Minutes'] = df.EventTime.apply(start_of_15_min)
df
# In[319]:
df.Seconds = df.Seconds.fillna(1)
df
# In[320]:
fin = df.groupby(['Customer', 'StartOf15Minutes', 'Status']).Seconds.sum().to_frame()
fin
# In[305]:
fin.Seconds.sum()
Idea是为第一个重复行和最后一个重复行创建的辅助数据帧,通过^{} 更改日期时间并通过^{} 连接在一起:
然后通过对每个组进行
ffill
重采样,删除每个组的最后一个值,并将size
聚合为秒数总和:相关问题 更多 >
编程相关推荐