Python 中 Pandas 的快速子集化
Posted
技术标签:
【中文标题】Python 中 Pandas 的快速子集化【英文标题】:Fast subsetting in Pandas in Python 【发布时间】:2019-04-15 12:26:58 【问题描述】:我正在运行一个循环数百万次,我需要在每个循环中对不同数量的数据进行子集化。我有一个数据框,它有两列,时间(这是一个时间序列)和电极,这表示当时触发的任何电极的数字在 1-64 之间。
time electrode
0 1
1 43
2 45
3 12
4 7
在每个循环中,我需要对数据进行子集化,例如:
num_electrodes = []
window_size = 5
index = 0
while index < len(data['time']) - interval_size:
start = data['time'][index]
end = data['time'][index+window_size]
window_data = data[(data['time'] >= start) & (data['time'] < end)]
num_electrodes.append(len(window_data['electrode'].unique()))
在下面的代码中,这里的代码真正慢的部分是对数据帧进行子集化并创建一个新的数据帧。
window_data = data[(data['time'] >= start) & (data['time'] < end)]
有什么好的选择吗?
【问题讨论】:
是你的time
系列字符串/datetime
/timedelta
/其他吗?
你什么时候增加索引,从多少开始?
@jpp 数据被标准化以从时间点“0”开始,然后继续到时间点 ~3600 分钟,增量为 ~0.001 分钟。
@B.M.我实际上在这里放了一个简化的例子,我只是想知道如何更快地对我的数据进行子集
【参考方案1】:
按您的时间排序,然后您可以使用 .loc 访问窗口开头和结尾的索引,然后选择一系列索引作为您的子集。
将您的 df 的索引设置为时间序列,然后使用 df.index.get_loc(beginning_window)
和 min(df.index.get_loc(beginning_window+window+1)) -1
获取您的索引范围。
非唯一索引的最小值。
然后使用 .iloc 选择该范围。
这应该会加快速度。
【讨论】:
我会试试这个......问题是我不仅选择了我在这个例子中给出的 index + 5 ,而且需要根据实际时间值找到窗口的结尾,所以这涉及到找到这个时间点的索引 使用 df.index.get_loc(time) 将索引设置为时间列后,即可找到该时间的索引。 我不知道具体时间,我需要在时间窗口内找到最后一次,然后找到索引。更复杂的是,多个电极可以同时触发,所以时间不是唯一值 如果你不知道你想从哪里开始你的窗口,没有其他人可以帮你确定。随机选择或经历所有可能性。更新了答案以适应非唯一索引【参考方案2】:假设您的数据按时间排序,您只需将电极按 5 分组即可。那么set
可以比np.unique
更快:
size=10**6
window_size=5
electrodes = np.random.randint(0,64,size)
electrodes_by_5 = electrodes.reshape(-1,window_size)
nb_electrodes=np.apply_along_axis(lambda arr:len(set(arr)),1,electrodes_by_5)
输出:
In [463]: electrodes[:10]
Out[463]: array([13, 13, 23, 20, 5, 30, 9, 6, 28, 11])
In [464]: electrodes_by_5[:2]
Out[464]:
array([[13, 13, 23, 20, 5],
[30, 9, 6, 28, 11]])
In [465]: nb_electrodes[:2]
Out[465]: array([4, 5])
【讨论】:
【参考方案3】:所以我通过切换到 numpy.ndarray 解决了这个问题,它比 iloc 索引快得多。
【讨论】:
以上是关于Python 中 Pandas 的快速子集化的主要内容,如果未能解决你的问题,请参考以下文章