title: Pandas: Apply a function aware of column type to every column of a data frame
body: <h1>Goal</h1>
  
  <p>I would like to apply a function that depends on the input column's type to every column in a data frame. Consider the following data frame:</p>
  
  <pre><code>df = pd.DataFrame( [["a",1],["b",2]], columns = ["string","num"] )
  </code></pre>
  
  <p>I can test for a column's type:</p>
  
  <pre><code>&gt;&gt;&gt; df["num"].dtype            
  dtype('int64')
  &gt;&gt;&gt; df["num"].dtype in ["int64"]
  True
  </code></pre>
  
  <p>And I can apply a function over all columns:</p>
  
  <pre><code>&gt;&gt;&gt; df . apply( lambda column: column.sum() )
  string    ab
  num        3
  dtype: object
  </code></pre>
  
  <p>But if I make the function depend on the column's type, I get garbage:</p>
  
  <pre><code>&gt;&gt;&gt; df . apply( lambda column:
  ...             np.nan if not column.dtype in ['float64','float32','int32','int64']
  ...             else column.sum() )
  string   NaN
  num      NaN
  dtype: float64
  </code></pre>
  
  <h1>Motivation</h1>
  
  <p>There are solutions that involve basically dropping the non-numeric columns, but I actually need to retain them. The reason for that is I'm trying to append a row that counts the zeroes in each column to the results of df.describe. Here's an example of a similar function:</p>
  
  <pre><code>def describe_plus(df):
    most_stats = df.describe()
    missing_stat = pd.DataFrame( df.isnull().sum()
                               , columns = ["missing"]
                               ).transpose()
    length_stat = pd.DataFrame( [[len(df) for _ in df.columns]]
                              , index = ["length"]
                              , columns = df.columns )
    return length_stat.append( missing_stat.append( most_stats ) )
  </code></pre>
  
  <p>Calling that gives you the ordinary output from pd.describe, plus the length and number missing in each column:</p>
  
  <pre><code>&gt;&gt;&gt; describe_plus( df )
                num  string
  length   2.000000     2.0
  missing  0.000000     0.0
  count    2.000000     NaN
  mean     1.000000     NaN
  std      1.414214     NaN
  min      0.000000     NaN
  25%      0.500000     NaN
  50%      1.000000     NaN
  75%      1.500000     NaN
  max      2.000000     NaN
  </code></pre>
  
  <p>In addition to length and missing, I would like to add a third row to describe_plus, which counts the number of zeroes in each column, or provides NaN for columns that are not numbers.</p>
  
  <h1>Edit: RafaelC's solution, in this framework</h1>
  
  <p>The trick is to discard those non-numeric variables, compute the summary statistics, and then simply append the other statistics (which are defined over every column, even non-numeric ones).</p>
  
  <pre><code>def describe_plus_plus(df):
    nums = df.select_dtypes(include=[np.number])
    zeroes = pd.DataFrame( [nums.apply( lambda col: len( col[col==0] ) / 
  len(nums) )] )
    return zeroes.append( describe_plus( df ) )
  </code></pre>
  
  <p>Example of it in action:</p>
  
  <pre><code>&gt;&gt;&gt; df = pd.DataFrame( [[0,0,0,""],[0,0,1,"a"],[0,1,2,"b"]], columns = ["none","1/3","2/3","string"] )
  &gt;&gt;&gt; describe_plus_plus( df )
                1/3       2/3  none  string
  0        0.666667  0.333333   1.0     NaN
  length   3.000000  3.000000   3.0     3.0
  missing  0.000000  0.000000   0.0     0.0
  count    3.000000  3.000000   3.0     NaN
  mean     0.333333  1.000000   0.0     NaN
  std      0.577350  1.000000   0.0     NaN
  min      0.000000  0.000000   0.0     NaN
  25%      0.000000  0.500000   0.0     NaN
  50%      0.000000  1.000000   0.0     NaN
  75%      0.500000  1.500000   0.0     NaN
  max      1.000000  2.000000   0.0     NaN
  </code></pre>