我有一个数据框,包含操作ID和事件开始和结束的日期时间戳。
OperID Start End
141 2014-03-04 19:28:39 2014-03-04 19:33:38
10502 2014-03-04 02:26:26 2014-03-08 20:09:21
10502 2014-03-15 00:03:45 2014-03-15 10:03:44
我想获取这些数据,并能够轻松创建各种类型的垃圾箱(月,日,小时) 表明操作处于受影响状态的每个箱内有多长。开始日期和结束日期通常跨越小时,日和月边界。
如果我白天打包,我想要的输出看起来像是:
OperID Bin Seconds
141 2014-03-04 299
10502 2014-03-04 77614
10502 2014-03-05 86400
10502 2014-03-06 86400
10502 2014-03-07 86400
10502 2014-03-08 72561
10502 2014-03-15 35999
答案 0 :(得分:1)
这是一个非常冗长的解决方案,循环很难摆脱:
In [3]:
from collections import OrderedDict
In [4]:
df['End_d']=pd.DatetimeIndex(df['End']).day
df['Start_d']=pd.DatetimeIndex(df['Start']).day
In [5]:
print df
OperID Start End End_d Start_d
0 141 2014-03-04 19:28:39 2014-03-04 19:33:38 4 4
1 10502 2014-03-04 02:26:26 2014-03-08 20:09:21 8 4
2 10502 2014-03-15 00:03:45 2014-03-15 10:03:44 15 15
[3 rows x 5 columns]
In [6]:
df.dtypes
Out[6]:
OperID int64
Start datetime64[ns]
End datetime64[ns]
End_d int32
Start_d int32
dtype: object
In [7]:
df1=df[df.End_d==df.Start_d].loc[:,['OperID', 'Start','End']] #the obs. of which the duration < 1day
df2=df[df.End_d!=df.Start_d] #the obs. of which the duration > 1day
for i in df2.index: #Expend it in to multiple rows.
days=df2.loc[i,:].End_d-df2.loc[i,:].Start_d+1
start_d_str=df2.loc[i,:].Start.strftime('%Y-%m-%d')
temp_df=pd.DataFrame(OrderedDict({'OperID': df2.loc[i,:].OperID,
'Start': pd.date_range('%s 00:00:00'%start_d_str, periods=days),
'End': pd.date_range('%s 23:59:59'%start_d_str, periods=days)}))
temp_df.loc[0,'Start'] = df2.loc[i,'Start']
temp_df.loc[days-1, 'End'] = df2.loc[i,'End']
df1=df1.append(temp_df)
df1['Bin']=pd.DatetimeIndex(df1.Start.apply(lambda x: x.strftime('%Y-%m-%d'))) #Get the YMD only
df1['Seconds']=(df1['End']-df1['Start'])/np.timedelta64(1,'s') #Convert to seconds
df1.sort(columns=['OperID', 'Start'], ascending=[-1,-1], inplace=True)
print df1
End OperID Start Bin Seconds
0 2014-03-04 19:33:38 141 2014-03-04 19:28:39 2014-03-04 299
0 2014-03-04 23:59:59 10502 2014-03-04 02:26:26 2014-03-04 77613
1 2014-03-05 23:59:59 10502 2014-03-05 00:00:00 2014-03-05 86399
2 2014-03-06 23:59:59 10502 2014-03-06 00:00:00 2014-03-06 86399
3 2014-03-07 23:59:59 10502 2014-03-07 00:00:00 2014-03-07 86399
4 2014-03-08 20:09:21 10502 2014-03-08 00:00:00 2014-03-08 72561
2 2014-03-15 10:03:44 10502 2014-03-15 00:03:45 2014-03-15 35999
[7 rows x 5 columns]
此外,如果您将1天计为86400秒而不是86299秒,那么您是否计算两次最后一秒(两天内)?无论如何都是小问题。