title: Making a better summary statistics table with plyr in R
body: <p>Every time I get a new data set the first thing I do is check out the summary statistics. The <code>summary</code> function does a pretty good job, but I'm frequently interested in standard deviations, quantiles with different breakpoints, number of observations, etc. Also, the presentation of <code>summary</code> isn't really the easiest way to digest or what you see in journals (i.e., <code>summary</code> is horizontal instead of vertical).</p>
  
  <p>For example, here is what I get from summary with some made up data.</p>
  
  <pre><code>&gt; library(plyr)
  &gt; library(reshape2)
  &gt; my.data &lt;- data.frame(firm = factor(rep(letters[1:5], each = 5)), returns = rnorm(n = 5 * 5), leverage = rep(c(0.3, 0.4, 0.5, 0.6, 0.7), each = 5) + .... [TRUNCATED] 
  &gt; my.summary &lt;- summary(my.data)
  &gt; my.summary
   firm     returns           leverage     
   a:5   Min.   :-1.6765   Min.   :0.2863  
   b:5   1st Qu.:-0.6945   1st Qu.:0.3929  
   c:5   Median :-0.1930   Median :0.5061  
   d:5   Mean   :-0.1159   Mean   :0.5009  
   e:5   3rd Qu.: 0.4323   3rd Qu.:0.6011  
         Max.   : 1.1915   Max.   :0.7093  
  </code></pre>
  
  <p>But let's say I really want something more like this.</p>
  
  <pre><code>&gt; my.manual.summary &lt;- data.frame(mean = c(mean(my.data$returns), mean(my.data$leverage)), median = c(median(my.data$returns), median(my.data$leverage .... [TRUNCATED] 
  &gt; rownames(my.manual.summary) &lt;- c("returns", "leverage")
  &gt; my.manual.summary
                 mean     median        sd
  returns  -0.1158633 -0.1929571 0.6996548
  leverage  0.5008895  0.5061301 0.1453381
  </code></pre>
  
  <p>For this small data set (i.e., just a few firm characteristics) this is easy. But I have more or what to do more statistics or more slicing-dicing, it can get tedious.</p>
  
  <p>I tried this with <code>reshape2</code> and <code>plyr</code>, but get an error.</p>
  
  <pre><code>&gt; my.melted.data &lt;- melt(my.data)
  Using firm as id variables
  &gt; my.improved.summary &lt;- ddply(my.melted.data[, -1], .(variable), c("mean", "median", "sd"), na.rm = T)
  Error in proto[[i]] &lt;- fs[[i]](x, ...) : 
    more elements supplied than there are to replace
  In addition: Warning messages:
  1: In mean.default(X[[1L]], ...) :
    argument is not numeric or logical: returning NA
  2: In mean.default(sort(x, partial = half + 0L:1L)[half + 0L:1L]) :
    argument is not numeric or logical: returning NA
  3: In var(as.vector(x), na.rm = na.rm) : NAs introduced by coercion
  4: In mean.default(X[[1L]], ...) :
    argument is not numeric or logical: returning NA
  </code></pre>
  
  <p>This leaves me with two questions:</p>
  
  <ol>
  <li>What am I doing wrong with <code>ddply</code>?</li>
  <li>Am I re-inventing the wheel here? Given that this is table 1 in everything I read and write, is there an existing solution that I haven't found?</li>
  </ol>
  
  <p>Thanks!</p>