布尔索引中列表推导的性能

时间:2017-02-15 21:13:43

标签: python performance pandas

我目前正在尝试了解有关Pandas的更多信息,并且正在查看文档中的Boolean Indexing部分。

在给出的示例中,注意到对于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)})

Big Series基准

%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方法通常实际上比布尔索引的列表推导更快吗?为什么列表理解方法在这里看起来实际上更快并且与documentation section相矛盾?

我的基准测试方法或测试中可能存在错误,我很清楚,对于更复杂的标准(甚至是简单的标准),前两种方法中的一种很多更好看看并实施,但我的问题只是表现。

注意:我使用的是Pandas版本0.18.1

1 个答案:

答案 0 :(得分:2)

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