2012-07-19 25 views
1

a previous question跟進有效的方法,有一個優選的有效的方式,以一列內獲得的每個對象的類型?這是專門爲在列的dtypeobject以允許異構類型的列的元素中的情況下(特別地,允許數字NaN而不改變其他元件的數據類型到float)。用於獲取的elementwise類型在Python /大熊貓

我還沒有完成時間基準測試,但是我懷疑以下立即明顯的想法(以及可能使用mapfilter的變體)。感興趣的用例需要快速獲取有關所有元素類型的信息,因此生成器等可能不會成爲效率優勢。

# df is a pandas DataFrame with some column 'A', such that 
# df['A'].dtype is 'object' 

dfrm['A'].apply(type) #Or np.dtype, but this will fail for native types. 

另一個想法是使用NumPy的vectorize功能,但是這真的會是更有效率?例如,與上面相同的設置,我可以嘗試:

import numpy as np 
vtype = np.vectorize(lambda x: type(x)) # Gives error without lambda 

vtype(dfrm['A']) 

兩個想法導致可行的輸出,但它是我擔心的效率。

新增

我繼續做在IPython中一個微小的標杆。首先是vtype以上,然後是apply路線。我重複了十幾次,這個例子在我的機器上非常典型。

apply()方法明顯勝出,那麼是否有充分的理由期望我的效率低於apply()

對於vtype()

In [49]: for ii in [100,1000,10000,100000,1000000,10000000]: 
    ....:  dfrm = pandas.DataFrame({'A':np.random.rand(ii)}) 
    ....:  dfrm['A'] = dfrm['A'].astype(object) 
    ....:  dfrm['A'][0:-1:2] = None 
    ....:  st_time = time.time() 
    ....:  tmp = vtype(dfrm['A']) 
    ....:  ed_time = time.time() 
    ....:  print "%s:\t\t %s"%(ii, ed_time-st_time) 
    ....:  
100:   0.0351531505585 
1000:  0.000324010848999 
10000:  0.00209212303162 
100000:  0.0224051475525 
1000000:  0.211136102676 
10000000: 2.2215731144 

對於apply()

In [50]: for ii in [100,1000,10000,100000,1000000,10000000]: 
    ....:  dfrm = pandas.DataFrame({'A':np.random.rand(ii)}) 
    ....:  dfrm['A'] = dfrm['A'].astype(object) 
    ....:  dfrm['A'][0:-1:2] = None 
    ....:  st_time = time.time() 
    ....:  tmp = dfrm['A'].apply(type) 
    ....:  ed_time = time.time() 
    ....:  print "%s:\t %s"%(ii, ed_time-st_time) 
    ....:  
100:   0.000900983810425 
1000:  0.000159025192261 
10000:  0.00117015838623 
100000:  0.0111050605774 
1000000:  0.103563070297 
10000000: 1.03093600273 
+1

小記:'拉姆達X:式(X)'會比簡單的慢'type',我想。 – DSM 2012-07-19 03:20:46

+0

是的,的確如此。不需要lambda。編輯。 – ely 2012-07-19 03:23:24

+0

儘管對於我的'vtype'函數,當我沒有用lambda定義它時,我得到一個錯誤。 – ely 2012-07-19 03:26:20

回答

3

Series.applySeries.map使用一個專門的用Cython方法(pandas.lib.map_infer)我寫了大約2倍比使用numpy.vectorize更快。

+0

我很欣賞這些反饋。我們也注意到,對於小基準測試(不超過10,000,000長列),似乎代碼'DFRM [「A」]。應用(類型).unique()'執行基本上只是一樣'設置([類型(X),用於DFRM X [「A」]如果x不是無])'...這是因爲一些NumPy的開銷在結束時返回一個NumPy的數組? – ely 2012-07-19 18:30:39

+0

我認爲在這兩種情況下你都會受到散列表性能的限制。但我可能是錯的;將獨特的內部結果轉換爲ndarray會有額外的開銷,所以我相信會有所貢獻。 – 2012-07-23 23:00:59