我有一个从字典列表创建的 DataFrame,它是从数据库中获取的。我正在尝试将其用作内存数据库,我使用以下函数进行查询:
def filter_entities(df, name1, name2):
key = ((df.name1 == name1) &
(df.name2 == name2))
rows = df.loc[key]
if len(rows) == 0:
return None
return rows.iloc[0]
Run Code Online (Sandbox Code Playgroud)
这样做似乎比我预期的要慢得多。即使对几百行进行测试,每次调用也需要大约 1 毫秒。我在创建数据框时尝试在这些列上设置索引,但它没有影响性能:
entities.set_index(['name1', 'name2'], drop=False, inplace=True)
Run Code Online (Sandbox Code Playgroud)
这是创建用于测试的数据集的快速方法:
import random, string
import pandas as pd
df = pd.DataFrame([{
'name1': ''.join([random.choice(string.letters) for i in range(10)]),
'name2': ''.join([random.choice(string.letters) for i in range(10)]),
'val1': random.randint(0, 2**16),
'val2': random.randint(0, 2**16),
'val3': random.randint(0, 2**16),
} for j in range(1000)])
In[27]: %timeit filter_entities(df, df['name1'][100], df['name2'][100])
1000 loops, best of 3: 1.91 ms per loop
Run Code Online (Sandbox Code Playgroud)
我正在尝试找到一种有效的方法来查询我的数据。有没有更好的方法在熊猫中做到这一点?
将列设置为索引确实提高了我的性能。
\n\n与你原来的filter_entities功能:
In [25]: %timeit filter_entities(df, df['name1'][100], df['name2'][100])\n\n1000 loops, best of 3: 1.36 ms per loop\nRun Code Online (Sandbox Code Playgroud)\n\n将列设置为索引后,然后对该帧建立索引:
\n\nIn [26]: df2 = df.set_index(['name1', 'name2'])\n\nIn [27]: %timeit df2.loc[df['name1'][100], df['name2'][100]]\n10000 loops, best of 3: 160 \xc2\xb5s per loop\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,函数中花费的大部分时间filter_entities用于布尔比较(创建key,而不是索引本身)。
第二个注意事项:如果这种规模的性能对您很重要,那么在许多情况下,如果您需要以这种方式重复访问各个行,或者您是否可以更加矢量化,那么考虑更大的情况也是有用的。
\n