title: Efficient method for getting elementwise types in Python/Pandas
body: <p>Following up on <a href="https://stackoverflow.com/questions/11548005/numpy-or-pandas-keeping-array-type-as-integer-while-having-a-nan-value">a previous question</a>, is there a preferred efficient manner to get the type of each object within a column? This is specifically for the case where the <code>dtype</code> of the column is <code>object</code> to allow for heterogeneous types among the elements of the column (in particular, allowing for numeric <code>NaN</code> without changing the data type of the other elements to <code>float</code>).</p>
  
  <p>I haven't done time benchmarking, but I am skeptical of the following immediately obvious way that comes to mind (and variants that might use <code>map</code> or <code>filter</code>). The use cases of interest need to quickly get info on the types of all elements, so generators and the like probably won't be an efficiency boon here. </p>
  
  <pre><code># 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.
  </code></pre>
  
  <p>Another thought was to use the NumPy <code>vectorize</code> function, but is this really going to be more efficient? For example, with the same setup as above, I could try:</p>
  
  <pre><code>import numpy as np
  vtype = np.vectorize(lambda x: type(x)) # Gives error without lambda
  
  vtype(dfrm['A'])
  </code></pre>
  
  <p>Both ideas lead to workable output, but it's the efficiency I'm worried about.</p>
  
  <p><strong>Added</strong></p>
  
  <p>I went ahead and did a tiny benchmark in IPython. First is for <code>vtype</code> above, then for the <code>apply</code> route. I repeated it a dozen or so times, and this example run is pretty typical on my machine.</p>
  
  <p>The <code>apply()</code> approach clearly wins, so is there a good reason to expect that I won't get more efficient than with <code>apply()</code>?</p>
  
  <p><strong>For <code>vtype()</code></strong></p>
  
  <pre><code>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
  </code></pre>
  
  <p><strong>For <code>apply()</code></strong></p>
  
  <pre><code>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
  </code></pre>