Pandas:通过创建索引来加速过滤?

5 投票
3 回答
5043 浏览
提问于 2025-04-17 14:55

我想在一个网页应用中像用SQL那样使用pandas(因为数据量不到1GB,而且不经常变化,所以不想用pSQL来存储数据,只想用pandas的DataFrame来存)。如果我想根据多个条件来查找数据,比如说年龄大于x、年龄小于y、收入大于p、收入小于q,有没有什么方法可以加快这个过滤的速度?或者说下面的内容已经解决了这个问题。在SQL中,我们会为年龄和收入建立索引来加速查询,我想知道在pandas中有没有类似的方法。

3 个回答

1

当处理一个超过四千万行的数据表(dfBig)时,使用布尔索引(在循环中)变得非常慢。

这里有一些伪代码对我有用;基本上是把 dfBig 用 df.groupby() 分成一个字典,然后用字典里的内容来代替直接索引:

# very slow version:
colValues = dfBig.SomeField1.unique()
indValues = dfBig.SomeField2.unique()
dfResult = ... # set up output dataframe
for col in colValues:
    for idx in indValues:
        boolIndex = (dfBig.SomeField1 == col) & (dfBig.SomeField2 == idx)
        fetchValue = dfBig[boolIndex]   # this takes a looong time
        dfResult.loc[idx, col] = someFuncion(fetchValue)


# much faster version:
dicCol = {x:y for x,y in df.groupby(SomeField1)}
for col,dfCol in dicCol.items():
    dfIdx = {x:y for x,y in dfCol.groupby(SomeField2)}
    for idx, dfIdx in dicIdx.items():
        dfResult.oc[idx, col] = someFunction(dfIdx)

这个“更快的版本”让处理这个四千万行的数据表速度提升了大约一百倍。

3

Pandas其实就是一个围绕着numpy.ndarray的包装工具。

所有的搜索操作实际上都是在用ndarray内部进行的。

 df[(df.age > x) & (y < df.age) & (df.income > p) & (df.income < q)]

这样做应该没问题。不过,你可以通过直接使用numpy.ndarray或者使用掩码数组来加快这个过程:http://docs.scipy.org/doc/numpy/reference/maskedarray.html

这样做不会为你新生成的数组分配新的内存。这意味着你不需要花时间和CPU去寻找和分配新的内存来存放你的“过滤”结果,也不会因为复制本身而增加内存的使用。(其实这并不完全正确,因为掩码还是需要存储在某个地方,但你仍然不需要把你的表格复制到内存的其他地方)

不过,这样做也有代价:使用掩码数组时,处理起来会稍微慢一些,因为系统需要检查内存中的每个值是否被掩码。不过,如果只是用来“过滤”,这种额外的访问时间应该是感觉不到的(当你想用掩码数组进行计算时,这个问题就变得很重要了)。

编辑:

为了在磁盘和内存中实现持久和优化的数据访问,可以使用PyTables,它是为此优化的。不过,Pytables以及Numpy/Pandas并不是为了这样使用而设计的。

7

用“pandas”的方式来做这个查询是:

df[(x < df.age) & (df.age < y) & (p < df.income) & (df.income < q)]

pandas 默认会对所有东西进行索引,包括所有的列,所以你不需要提前明确声明你要查询的内容。

(我不能确定这种设置对你的数据集是否合适。)

撰写回答