寻找最快的方法来切片一行在一个巨大的Pandas数据框架

k2fxgqgv  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(99)

我的程序需要从一个巨大的Pandas Dataframe中根据列中的值获取一行。响应时间很关键。我使用最常见的方法来完成它,例如:

df.loc[df['id'] == 500000, :]

字符串
在我的Mac上,每timeit需要4毫秒才能在一个有100万行的嵌套框架上完成上述操作。但我的目标是将时间减少到0.4毫秒。我曾经考虑将这个嵌套框架转换为Set,但Set不是有序的,并且本身不支持索引或切片。有什么建议吗?

olhwl3o2

olhwl3o21#

让我们设置这个:

import pandas as pd
import numpy as np
df = pd.DataFrame({"id": np.random.randint(100,size=(1000000,))})

字符串
然后让我们对一些选项进行基准测试。您当前的boolean + .loc

>>> timeit.timeit("df.loc[df['id'] == 50, :]", setup = "from __main__ import df", number=1000)
2.566220869999597


查询引擎:

>>> timeit.timeit("df.query('id == 50')", setup = "from __main__ import df", number=1000)
14.591400260000228


使用索引作为单独的查找:

>>> idx = pd.Index(df['id'])
>>> timeit.timeit("df.loc[idx == 50, :]", setup = "from __main__ import df, idx", number=1000)
2.2155187300013495


使用索引进行查找:

>>> df.index = df["id"]
>>> timeit.timeit("df.loc[50, :]", setup = "from __main__ import df", number=1000)
2.625610274999417


评论中有人提出的.isin()想法:

>>> timeit.timeit("df.loc[df['id'].isin([50]), :]", setup = "from __main__ import df", number=1000)
9.542700138999862


看起来,除了查询引擎对于简单的等式很慢(正如预期的那样)之外,您不会得到比查找时间更好的结果。

df_unique = pd.DataFrame({'id': range(1000000)})


让我们看看一个唯一的ID可能会有帮助:

>>> timeit.timeit("df_unique.loc[df_unique['id'] == 50, :]", setup = "from __main__ import df_unique", number=1000)
1.9672015519990964


然后是一个命令:

>>> df_unique.index = df_unique['id']
>>> df_dict = df_unique.to_dict(orient='index')
>>> timeit.timeit("df_dict[50]", setup = "from __main__ import df_dict", number=1000)
6.247700002859347e-05


看起来这是一个明显的赢家。

>>> timeit.timeit("pd.Series(df_dict[50])", setup = "from __main__ import df_dict, pd", number=1000)
0.2747819870000967


即使你必须将它转换回一个序列,这也比以前快了一个数量级。(如果需要的话,你也可以很容易地将一个序列Map回dict,并保持dict查找的速度,而不会产生开销)

rnmwe5a2

rnmwe5a22#

检查工作速度 df.query('id == 500000')

ua4mk5z4

ua4mk5z43#

使用df.id.values
让我们创建一个包含1000000行的嵌套框架:

import pandas as pd
import numpy as np
np.random.seed(3)
df = pd.DataFrame({"id": np.random.randint(100,size=(1000000,))})

字符串
方法一:

%%time
df.loc[df['id'] == 50, :]
#CPU times: user 6.64 ms, sys: 57 µs, total: 6.69 ms
#Wall time: 5.39 ms


的数据
方法二:

%%time
df.loc[df.id.values == 50, :]
#CPU times: user 3.97 ms, sys: 0 ns, total: 3.97 ms
#Wall time: 2.82 ms


  • 注意:本例中,输出的数组有9915行,而且速度似乎与查询的值和原始的df结构有关。*
    让我们使用timeit模块对测试进行基准测试。

方法一:

import timeit
timeit.timeit("df.loc[df['id'] == 50, :]", setup = "from __main__ import df", number=1000)
#1.5578972157090902


方法二:

timeit.timeit("df.loc[df.id.values == 50, :]", setup = "from __main__ import df", number=1000)
#1.3210897352546453

相关问题