Pandas 熊猫:将数据划分为15分钟

Pandas 熊猫:将数据划分为15分钟,pandas,timedelta,Pandas,Timedelta,我有数据框和日期看起来像 event_time 2017-01-17 00:12:50 2016-12-05 01:00:21 2016-12-04 01:14:36 2016-12-04 01:04:03 2016-12-04 02:28:23 2016-12-04 02:46:49 2016-12-04 01:58:04 我需要获取列period,其中15分钟从00:00:00开始,日期、月份和年份不重要。 时间在00:00

我有数据框和日期看起来像

event_time
2017-01-17 00:12:50      
2016-12-05 01:00:21      
2016-12-04 01:14:36     
2016-12-04 01:04:03     
2016-12-04 02:28:23     
2016-12-04 02:46:49      
2016-12-04 01:58:04
我需要获取列
period
,其中15分钟从
00:00:00开始,日期、月份和年份不重要。
时间在
00:00:00-00:15:00
-时段1
00:15:01-00:50:00
-第2段等。 如果我使用
df=df.groupby(pd.TimeGrouper(freq='15Min'))
它是错误的,因为它也使用day。但我只需要利用时间

期望输出

event_time            period
2017-01-17 00:12:50   1      
2016-12-05 01:00:21   4    
2016-12-04 01:14:36   4 
2016-12-04 01:04:03   4 
2016-12-04 02:28:23   10  
2016-12-04 02:46:49   12 
2016-12-04 01:58:04   8
我该怎么做

df = pd.DataFrame(pd.to_datetime([
    "2017-01-17 00:12:50",    
    "2016-12-05 01:00:21",      
    "2016-12-04 01:14:36",     
    "2016-12-04 01:04:03",     
    "2016-12-04 02:28:23",     
    "2016-12-04 02:46:49",      
    "2016-12-04 01:58:04"]),
    columns=['timestamp']
    )
然后是
period

df['period'] = df.timestamp.apply(lambda ts: 1 + ts.hour * 4 + ts.minute // 15)
它提供了以下输入:

            timestamp  period
0 2017-01-17 00:12:50       1
1 2016-12-05 01:00:21       5
2 2016-12-04 01:14:36       5
3 2016-12-04 01:04:03       5
4 2016-12-04 02:28:23      10
5 2016-12-04 02:46:49      12
6 2016-12-04 01:58:04       8
您和我的输出之间存在微小差异-行
1
2
3
:例如
01:00:21
应该是
5
,因为在第一个小时和第五个小时有四个时段刚刚开始。

新的解决方案包括和:

计时

rng = pd.date_range('2017-04-03', periods=100000, freq='27T')
df = pd.DataFrame({'timestamp': rng})  

df['label'] = df['timestamp'].dt.hour * 4 + df['timestamp'].dt.minute // 15 + 1
df['period'] = df.timestamp.apply(lambda ts: 1 + ts.hour * 4 + ts.minute // 15)
print (df)

In [172]: %timeit df['timestamp'].dt.hour * 4 + df['timestamp'].dt.minute // 15 + 1
10 loops, best of 3: 20.2 ms per loop

In [173]: %timeit df.timestamp.apply(lambda ts: 1 + ts.hour * 4 + ts.minute // 15)
1 loop, best of 3: 301 ms per loop
旧的解决方案(可行,但有点复杂):

您可以先将日期时间转换为,然后再转换为秒

然后使用或:


类似的解决方案,仅适用于
系列
tot:

tot = pd.to_timedelta(df['event_time'].dt.strftime('%H:%M:%S'))
       .dt.total_seconds()
       .astype(int)

bins = np.concatenate([np.arange(24 * 4) * 900, np.array([100000])])
labels = np.arange(1, 24 * 4 + 1)
df['label'] = pd.cut(tot, bins=bins, labels=labels)

df = df.assign(label1=np.searchsorted(bins, tot))
print (df)
           event_time label  label1
0 2017-01-17 00:12:50     1       1
1 2016-12-05 01:00:21     5       5
2 2016-12-04 01:14:36     5       5
3 2016-12-04 01:04:03     5       5
4 2016-12-04 02:28:23    10      10
5 2016-12-04 02:46:49    12      12
6 2016-12-04 01:58:04     8       8

我需要用数值将其添加到列中,然后您可以用所需的输出更新您的问题吗?我需要“period”列中的句号。您的代码返回句号,但对于time
00:05:05
它又返回32,我猜。如果我编辑的回复不是您想要的,没有示例,我将无法帮助您。我不需要求和)我需要获得包含句号的列。我已经更改了我的问题并添加了desire Output您是否注意到我在更新之前用相同的解决方案(不同的符号)给出了相同的答案?这很不公平。@mkos-我认为这是不同的解决方案,所以我添加了它。应用和矢量化的aprocha总是不同的。@mkos-但想法是一样的,你们是对的。我认为这没有问题。矢量化方法(在我的电脑上)比
apply()
慢约3倍,所以为什么还要麻烦更新?@mkos-它更快,因为测试的数据帧很小。检查我编辑的答案-应用速度较慢。
df['tot'] = pd.to_timedelta(df['event_time'].dt.strftime('%H:%M:%S'))
              .dt.total_seconds()
              .astype(int)

#necessary add one group
bins = np.concatenate([np.arange(24 * 4) * 900, np.array([100000])])
labels = np.arange(1, 24 * 4 + 1)
df['label'] = pd.cut(df['tot'], bins=bins, labels=labels)
df = df.assign(label1=np.searchsorted(bins, df['tot']))
print (df)
           event_time    tot label  label1
0 2017-01-17 00:12:50    770     1       1
1 2016-12-05 01:00:21   3621     5       5
2 2016-12-04 01:14:36   4476     5       5
3 2016-12-04 01:04:03   3843     5       5
4 2016-12-04 02:28:23   8903    10      10
5 2016-12-04 02:46:49  10009    12      12
6 2016-12-04 01:58:04   7084     8       8
tot = pd.to_timedelta(df['event_time'].dt.strftime('%H:%M:%S'))
       .dt.total_seconds()
       .astype(int)

bins = np.concatenate([np.arange(24 * 4) * 900, np.array([100000])])
labels = np.arange(1, 24 * 4 + 1)
df['label'] = pd.cut(tot, bins=bins, labels=labels)

df = df.assign(label1=np.searchsorted(bins, tot))
print (df)
           event_time label  label1
0 2017-01-17 00:12:50     1       1
1 2016-12-05 01:00:21     5       5
2 2016-12-04 01:14:36     5       5
3 2016-12-04 01:04:03     5       5
4 2016-12-04 02:28:23    10      10
5 2016-12-04 02:46:49    12      12
6 2016-12-04 01:58:04     8       8