python - 为什么 pandas 的索引这么慢?如何让它更快?
问题描述
运行此代码显示了 pandas 和常规 python 列表之间的速度差异:
ser = pd.Series(range(100))
lst = ser.tolist()
for _ in range(10):
pandas_time = 0
list_time = 0
for _ in range(100000):
r = randint(0, len(ser)-1)
t = time()
ser[r]
pandas_time += time() - t
t = time()
lst[r]
list_time += time() - t
print(pandas_time, list_time)
结果(索引随机元素 100000 次的 10 次试验):
Pandas Regular List
0.6404812335968018 0.03125190734863281
0.6560468673706055 0.0
0.5779874324798584 0.01562190055847168
0.5467743873596191 0.015621662139892578
0.6106545925140381 0.004016399383544922
0.5866603851318359 0.029597759246826172
0.7981059551239014 0.016004562377929688
0.8128316402435303 0.013040542602539062
0.5566465854644775 0.021578073501586914
0.6386256217956543 0.00500178337097168
索引 pandas 系列似乎比 python 列表慢 30 到 100 倍。为什么?我们怎样才能加快速度?
解决方案
我检查了pandas'
源代码。与常规 python 列表相比,pandas 系列中的__getitem__
实现有很多额外的业务逻辑,因为 pandas 系列支持使用列表和可迭代的索引。
索引 pandas 系列时,该系列:
如果密钥可调用,则尝试应用密钥
获取该键处的索引值(听起来很简单,但请记住,索引是另一个熊猫对象,它还必须支持比常规索引更多的功能)
检查 2) 是否为标量
如果是标量返回结果
__getitem__
与常规的 python 列表相比,这些额外的步骤大大减慢了速度。
要解决此问题,您可以直接使用底层 numpy 数组。这里我们使用ser.values
索引来代替:
ser = pd.Series(range(100))
lst = ser.tolist()
ser = ser.values
for _ in range(10):
pandas_time = 0
list_time = 0
for _ in range(1000000):
r = randint(0, len(ser)-1)
t = time()
ser[r]
pandas_time += time() - t
t = time()
lst[r]
list_time += time() - t
print(pandas_time, list_time)
在索引 1000000 个随机元素 10 次后,我们发现 using.values
比仅索引 pandas 系列要快得多,但仍然比使用 python 列表慢
pd.Series.values Regular List
0.18845057487487793 0.04786252975463867
0.10950899124145508 0.11034011840820312
0.048889875411987305 0.09512066841125488
0.17272686958312988 0.1406867504119873
0.14252233505249023 0.048066139221191406
0.06352949142456055 0.07906699180603027
0.1405477523803711 0.07815265655517578
0.18746685981750488 0.08007645606994629
0.1405184268951416 0.0781564712524414
0.07921838760375977 0.1412496566772461
总结.values
一下,当您需要快速索引熊猫系列时,使用是一种方法。虽然它看起来.tolist()
更快,但请记住,在索引单个元素时它只会稍微快一点。Numpy 数组将支持更快的花式索引,例如使用多个元素进行索引。
推荐阅读
- date - 查询 Google 表格中的时间戳以查找特定日期但忽略时间
- java - 如何将适当的成本应用于排名选择
- nginx - 如何删除仅适用于 Nginx 服务器的 html php 文件的 url 末尾的 html php 扩展名和斜杠
- c - 英特尔文档中的“受内存屏障保护的可选变量列表”是什么意思?
- laravel - 网站无法在 PC 上访问,但在手机上可以正常工作
- c# - 找不到属性 [TableName] 的存储信息
- php - 如何使用phpmyadmin恢复在sql中意外删除的表
- ruby-on-rails - 如何授予通过 Rails 控制台执行的 Ruby 脚本对 Digital Ocean 的写入权限?
- json - 在哪里/如何获得前 10,000 条维基百科文章标题,按页面浏览量?
- postgresql - 在测试环境中加载 structure.sql 需要 Rails 5 中的哪些 rake 任务?