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”列中的句号。您的代码返回句号,但对于time00: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