在Python pandas DataFrame中对接近的日期时间进行分组
我在这个问题上一直在苦苦挣扎,想知道有没有人能给我一些建议,告诉我该怎么处理。我有一个 pandas 的数据表,里面有很多列,其中有一列是日期时间格式。我想找到一种方法,把那些时间非常接近的记录“分组”在一起。比如说,如果一些交易在两秒内发生,我希望把它们放在一起,并给它们一个共同的标识,叫做“分组 ID”。
Transaction ID Time Grouped ID
1 08:10:02 1
2 08:10:03 1
3 08:10:50
4 08:10:55
5 08:11:00 2
6 08:11:01 2
7 08:11:02 2
8 08:11:03 3
9 08:11:04 3
10 08:15:00
需要注意的是,我并不想让这个时间窗口无限扩大。如果交易在很短的时间内继续发生,一旦过去了完整的两秒,下一笔交易就会开始一个新的时间窗口(就像交易 5 到 9 的情况)。另外,我最终会在毫秒级别进行这个分析(也就是说,把在 50 毫秒内的交易合并在一起),但为了简单起见,上面的例子我先用秒来说明。
非常感谢你们能提供的任何建议!
1 个回答
2
我建议的解决方案需要你用时间数据重新整理你的数据。你可以使用一个包含所需频率的日期时间列表,利用 searchsorted
来找到你索引中最接近的日期时间,然后用它来进行切片(就像在问题中提到的 python pandas 数据框按日期条件切片 和 Python pandas,如何截断 DatetimeIndex 并仅在特定区间填充缺失数据)。
我使用的是 pandas 0.14.1 和 DataOffset
对象(http://pandas.pydata.org/pandas-docs/dev/timeseries.html?highlight=dateoffset)。我没有检查 datetime64,但我猜你可以调整代码。 DataOffset
可以精确到微秒级别。
使用以下代码,
import pandas as pd
import pandas.tseries.offsets as pto
import numpy as np
# Create some ome test data
d_size = 15
df = pd.DataFrame({"value": np.arange(d_size)}, index=pd.date_range("2014/11/03", periods=d_size, freq=pto.Milli()))
# Define periods to define groups (ticks)
ticks = pd.date_range("2014/11/03", periods=d_size/3, freq=5*pto.Milli())
# find nearest indexes matching the ticks
index_ticks = np.unique(df.index.searchsorted(ticks))
# make a dataframe with the group ids
dgroups = pa.DataFrame(index=df.index, columns=['Group id',])
# sets the group ids
for i, (mini, maxi) in enumerate(zip(index_ticks[:-1], index_ticks[1:])):
dgroups.loc[mini:maxi] = i
# update original dataframe
df['Group id'] = dgroups['Group id']
我得到了这样的数据框:
value Group id
2014-11-03 00:00:00 0 0
2014-11-03 00:00:00.001000 1 0
2014-11-03 00:00:00.002000 2 0
2014-11-03 00:00:00.003000 3 0
2014-11-03 00:00:00.004000 4 0
2014-11-03 00:00:00.005000 5 1
2014-11-03 00:00:00.006000 6 1
2014-11-03 00:00:00.007000 7 1
2014-11-03 00:00:00.008000 8 1
2014-11-03 00:00:00.009000 9 1
2014-11-03 00:00:00.010000 10 2
2014-11-03 00:00:00.011000 11 2
2014-11-03 00:00:00.012000 12 2
2014-11-03 00:00:00.013000 13 2
2014-11-03 00:00:00.014000 14 2