布尔索引中列表综合的性能



我目前正在尝试了解有关熊猫的更多信息,并正在查看文档中的布尔索引部分。

在给出的示例中,请注意,对于dataframe

In[439]: df2 = pd.DataFrame({'a' : ['one', 'one', 'two', 'three', 'two', 'one', 'six'],
                             'b' : ['x', 'y', 'y', 'x', 'y', 'x', 'x'],
                             'c' : np.random.randn(7)})
In[440]: df2
Out[440]: 
       a  b         c
0    one  x -0.858441
1    one  y  0.643366
2    two  y -0.862198
3  three  x -0.408981
4    two  y  1.137740
5    one  x  0.829057
6    six  x -1.251656

使用

等系列的map方法
In [441]: criterion = df2['a'].map(lambda x: x.startswith('t'))
In [442]: df2[criterion]
Out[442]: 
       a  b         c
2    two  y  0.041290
3  three  x  0.361719
4    two  y -0.238075

比等效列表理解

In [443]: df2[[x.startswith('t') for x in df2['a']]]
Out[443]: 
       a  b         c
2    two  y  0.041290
3  three  x  0.361719
4    two  y -0.238075

现在,在这种情况下,我将使用文档中未提及的df2[df2.a.str.startswith('t')],因此我想对方法进行基准测试。


小型系列基准

%timeit df2[df2.a.str.startswith('t')]
1000 loops, best of 3: 880 µs per loop
%timeit df2[df2['a'].map(lambda x: x.startswith('t'))]
1000 loops, best of 3: 783 µs per loop
%timeit df2[[x.startswith('t') for x in df2['a']]]
1000 loops, best of 3: 572 µs per loop

令人惊讶的是,列表理解方法似乎是最快的!因此,我尝试使DataFrame 大大更大并再次进行基准测试。

In[444]: df2 = pd.DataFrame({'a' : ['one', 'one', 'two', 'three', 'two', 'one', 'six']*1000000,
                             'b' : ['x', 'y', 'y', 'x', 'y', 'x', 'x']*1000000,
                             'c' : np.random.randn(7*1000000)})

大系列基准

%timeit df2[df2.a.str.startswith('t')]
1 loop, best of 3: 5.89 s per loop
%timeit df2[df2['a'].map(lambda x: x.startswith('t'))]
1 loop, best of 3: 5.73 s per loop
%timeit df2[[x.startswith('t') for x in df2['a']]]
1 loop, best of 3: 3.95 s per loop

仍然是最快的列表理解,而大型系列的差异更为明显。


问题

系列的map方法通常比布尔索引的列表理解更快?为什么列表理解方法实际上在这里实际上更快,并且与文档部分相矛盾?

我的基准测试方法或测试可能会出现错误,我很清楚,对于更复杂的标准(甚至简单的标准),前两种方法之一是 toem toce 查看和实施,但我的问题只是绩效。

注意:我正在使用pandas版本0.18.1

imo,不是关于布尔索引 - 它是关于使用字符串系列:

In [204]: %timeit df.a.str.startswith('t')
10 loops, best of 3: 75.7 ms per loop
In [205]: %timeit df['a'].map(lambda x: x.startswith('t'))
10 loops, best of 3: 76.5 ms per loop
In [206]: %timeit [x.startswith('t') for x in df['a']]
10 loops, best of 3: 39.7 ms per loop
In [209]: %timeit [df.a.str[0] == 't']
10 loops, best of 3: 85.2 ms per loop

DF形状:70.000 x 3

In [207]: df.shape
Out[207]: (70000, 3)

使用string系列时,列表理解通常更快。

ps我正在使用pandas版本0.19.2用于此示例

最新更新