2012-07-19 42 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