2014-06-12 57 views
1

我想在熊貓列中搜索一個字符串。我已經讀過,它應該是最快排序的第一列和搜索字符串使用搜索排序值。我發現這比在同一個numpy數組上搜索蠻力(array == string)要慢。要知道爲什麼,我已經進行了以下試驗:python熊貓與numpy數組的搜索性能

import timeit 

setup4 = ''' 
import numpy as np, string, random 

d =  np.array([ 
      u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)) 
      for _ in range(20000) 
      ],dtype=np.object) 
''' 



setup5 = ''' 
import numpy as np, pandas as pd, string, random 

header = [ 
        u'A', 
        u'B', 
        u'C', 
        u'D', 
        u'E', 
        u'F', 
        u'G', 
        u'H', 
        u'I', 
        u'J', 
        u'K', 
        u'L', 
        u'M', 
        u'N' 
        ] 


data =  [[pd.to_datetime('20140505'), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u'sfgweorfjdfl', 
       u'dsiofqjwel;dmfv', 
       u'e3ruiwefjvgoiubg', 
       u'3124oirjrg;klhbas', 
       u';3rhfgfbnvsad3r', 
       pd.to_datetime('20140505'), 
       u'1234irtjurgbfas', 
       u'12;rhfd;hb;oasere', 
       u'124urgfdnv.,sadfg', 
       u'1rfnhsdjk.dhafgsrdew', 
       u'safeklrjh2nerfgsd.' 
       ] for _ in range(20000)] 

df = pd.DataFrame(data,columns=header) 
df_sorted = df.sort(['B','C']) 
e = df_sorted['B'].values 
''' 

setup6 = ''' 
import numpy as np, pandas as pd, string, random 

header = [ 
        u'A', 
        u'B', 
        u'C', 
        u'D', 
        u'E', 
        u'F', 
        u'G', 
        u'H', 
        u'I', 
        u'J', 
        u'K', 
        u'L', 
        u'M', 
        u'N' 
        ] 


data =  [[pd.to_datetime('20140505'), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u'sfgweorfjdfl', 
       u'dsiofqjwel;dmfv', 
       u'e3ruiwefjvgoiubg', 
       u'3124oirjrg;klhbas', 
       u';3rhfgfbnvsad3r', 
       pd.to_datetime('20140505'), 
       u'1234irtjurgbfas', 
       u'12;rhfd;hb;oasere', 
       u'124urgfdnv.,sadfg', 
       u'1rfnhsdjk.dhafgsrdew', 
       u'safeklrjh2nerfgsd.' 
       ] for _ in range(20000)] 

df = pd.DataFrame(data,columns=header) 
f = df['B'].values 
''' 

print(timeit.timeit("index = d == u'ASDASD123ASADKHX'", setup=setup4,number=1000)) 
print(timeit.timeit("index = e == u'ASDASD123ASADKHX'", setup=setup5,number=1000)) 
print(timeit.timeit("index = f == u'ASDASD123ASADKHX'", setup=setup6,number=1000)) 

結果如下:

print(timeit.timeit("index = d == u'ASDASD123ASADKHX'", setup=setup4,number=1000)) 
0.808505267014 

print(timeit.timeit("index = e == u'ASDASD123ASADKHX'", setup=setup5,number=1000)) 

3.06733738226 

print(timeit.timeit("index = f == u'ASDASD123ASADKHX'", setup=setup6,number=1000)) 
1.64207848896 

我的問題在這裏:爲什麼是純numpy的陣列上的表現好多了?我如何使用從熊貓表中提取的數據實現相同的性能?

非常感謝。

+1

我相信,大熊貓雖然用途它下面的numpy數組做更多的dtype檢查和對齊,所以更慢:http://stackoverflow.com/questions/19834075/pandas-much-slower-than-numpy – EdChum

+0

好吧,但在所有3例,我運行在numpy數組上進行。唯一的區別是對於第一種情況,數組本身被構造爲一個numpy數組,而在後兩種情況下,數組是使用「值」從熊貓數據框中提取的。 – Felix

+0

您的第二個設置是排序並返回數據幀的副本,第三個設置不會執行此操作,但似乎在構建數據幀時會有一些開銷,然後將數據作爲numpy數組返回。我不知道熊貓的全部內部工作原理來解釋更多的內容,但只需創建數據框就可以了,這樣就可以瞭解通過'.values將數據排序和訪問數據作爲一個numpy數組的成本。 ' – EdChum

回答

0

DataFrame中的每個字符串都是一個對象,您從df['B'].values得到的是對象數組。但是,當您通過np.array()創建字符串數組時,它會返回一個數組,每個字符串使用相同的字節數。

下面是一個示例,aS10 dtype的數組,b是一個帶有對象dtype的數組。

import numpy as np 
import random 
import string 
words = ["".join(random.choice(string.ascii_uppercase) for _ in range(10)) for _ in range(10000)] 
a = np.array(words) 
b = a.astype("O") 
%timeit a == "123" 
%timeit b == "123" 

輸出:

10000 loops, best of 3: 122 µs per loop 
10000 loops, best of 3: 164 µs per loop 
+0

是的,我已經意識到這一點。因此,numpy數組是'dtype = np.object'。它也不能解釋熊貓排序和未排序數組之間的差異(情況2和3)。 – Felix

0

我測試你的代碼在IPython中,並得到了幾乎所有相同的性能未排序的數據幀變種分開:

In [85]: 

import numpy as np, string, random 

d =  np.array([ 
      u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)) 
      for _ in range(20000) 
      ],dtype=np.object) 

header = [ 
        u'A', 
        u'B', 
        u'C', 
        u'D', 
        u'E', 
        u'F', 
        u'G', 
        u'H', 
        u'I', 
        u'J', 
        u'K', 
        u'L', 
        u'M', 
        u'N' 
        ] 


data =  [[pd.to_datetime('20140505'), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(16)), 
       u'sfgweorfjdfl', 
       u'dsiofqjwel;dmfv', 
       u'e3ruiwefjvgoiubg', 
       u'3124oirjrg;klhbas', 
       u';3rhfgfbnvsad3r', 
       pd.to_datetime('20140505'), 
       u'1234irtjurgbfas', 
       u'12;rhfd;hb;oasere', 
       u'124urgfdnv.,sadfg', 
       u'1rfnhsdjk.dhafgsrdew', 
       u'safeklrjh2nerfgsd.' 
       ] for _ in range(20000)] 

df = pd.DataFrame(data,columns=header) 
df_sorted = df.sort(['B','C']) 
e = df_sorted['B'].values 
f = df['B'].values 
%timeit index = d == u'ASDASD123ASADKHX' 
%timeit index = e == u'ASDASD123ASADKHX' 
%timeit index = f == u'ASDASD123ASADKHX' 
1000 loops, best of 3: 536 µs per loop 
1000 loops, best of 3: 568 µs per loop 
1000 loops, best of 3: 538 µs per loop 
+0

這很有趣。如果您完全按照上面所述使用代碼,會發生什麼情況?我添加了'import timeit',所以它現在應該是一個自洽的python文件。 – Felix

+0

我跑你的代碼,並得到如下:'2.11338382930262 1.2496556612022687 0.6459569358412409'是相反你觀察到的東西,然後我又跑,並得到'0.5910921373142628 1.7401513672084548 0.5598322421719786'如果你重新運行你的代碼你得到隨機的結果? – EdChum

+0

只是跑了一遍,得到了'0.5474049547920004 0.6093832207843661 0.5601899379689712',這裏對我來說似乎不是什麼謎 – EdChum