我有一个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]
这样做似乎比我预期的要慢得多。即使在几百行上进行测试,每次调用大约需要1毫秒。我在创建数据帧时尝试在这些列上设置索引,但它不会影响性能:
entities.set_index(['name1', 'name2'], drop=False, inplace=True)
以下是创建测试数据集的快捷方法:
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
我正在尝试找到一种有效的方法来查询我的数据。在熊猫中有更好的方法吗?
答案 0 :(得分:1)
将列设置为索引确实可以改善我的性能。
使用原始filter_entities
功能:
In [25]: %timeit filter_entities(df, df['name1'][100], df['name2'][100])
1000 loops, best of 3: 1.36 ms per loop
将列设置为索引,然后将该索引编入索引:
In [26]: df2 = df.set_index(['name1', 'name2'])
In [27]: %timeit df2.loc[df['name1'][100], df['name2'][100]]
10000 loops, best of 3: 160 µs per loop
请注意,在filter_entities
函数中花费的大部分时间用于布尔比较(创建key
,而不是用于索引本身)。
第二个注意事项:如果这个等级的表现对你很重要,那么在很多情况下,如果你需要反复以这种方式访问各个行,或者你可以做更多的矢量化,那么考虑更大的图片也是有用的。
答案 1 :(得分:0)
是。这可以在熊猫中进行。我为该示例创建了一些示例数据。
以下行为“name1”等于bob且“name2”等于greg的列的数据框设置子集。
df[(df['name1'] == 'bob') & (df['name2'] == 'greg')]
完整代码:
import pandas as pd
data = [{'name1': 'bob', 'name2': 'greg', 'value': 1},
{'name1': 'bob', 'name2': 'greg', 'value': 2},
{'name1': 'jim', 'name2': 'greg', 'value': 3},
{'name1': 'bob', 'name2': 'greg', 'value': 4},
{'name1': 'bob', 'name2': 'tim', 'value': 5},
{'name1': 'bob', 'name2': 'jo', 'value': 6}]
df = pd.DataFrame(data)
print df[(df['name1'] == 'bob') & (df['name2'] == 'greg')]
name1 name2 value
0 bob greg 1
1 bob greg 2
3 bob greg 4
def filter_entities(entities, name1, name2):
key = ((entities.name1 == name1) &
(entities.name2 == name2))
rows = entities.loc[key]
if len(rows) == 0:
return None
return rows.iloc[0]
%timeit test1 = df[(df['name1'] == 'bob') & (df['name2'] == 'greg')]
%timeit test2 = filter_entities(df, 'bob', 'greg')
100 loops, best of 3: 2.02 ms per loop
100 loops, best of 3: 2.31 ms per loop
答案 2 :(得分:0)
更改此行:
df[(df['name1'] == 'bob') & (df['name2'] == 'greg')]
对此:
df2 = df[(df['name1'] == 'bob')]
df3 = df2[(df2['name2'] == 'greg')]
为我减少了一半的时间。