From: Skipper S. <jss...@gm...> - 2012-11-16 15:58:59
|
On Fri, Nov 16, 2012 at 10:19 AM, Yaroslav Halchenko <sf...@on...> wrote: > I just found some code (http://www.onerussian.com/tmp/plots.py and > pasted below for review/feedback) laying around which I wrote around > matplotlib for plotting primarily pair-wise stats results. Here is a > demonstration: > http://nbviewer.ipython.org/url/www.onerussian.com/tmp/run_plots.ipynb > > I wonder if there is a need/place for it in matplotlib and what changes would > you advise. Sorry for the lack of documentation -- I guess I have not finished > it at that point (scipy dependency can easily be dropped, used only for > standard error function iirc): > Looks nice. We'd certainly be interesting in including it in statsmodels/graphics if there isn't sufficient interest here and/or you'd like to keep the scipy dependency. ;) Skipper > #!/usr/bin/python > #emacs: -*- mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: nil -*- > #ex: set sts=4 ts=4 sw=4 noet: > #------------------------- =+- Python script -+= ------------------------- > """ > @file paired-plots.py > @date Fri Jan 13 11:48:00 2012 > @brief > > > Yaroslav Halchenko Dartmouth > web: http://www.onerussian.com College > e-mail: yo...@on... ICQ#: 60653192 > > DESCRIPTION (NOTES): > > COPYRIGHT: Yaroslav Halchenko 2012 > > LICENSE: MIT > > Permission is hereby granted, free of charge, to any person obtaining a copy > of this software and associated documentation files (the "Software"), to deal > in the Software without restriction, including without limitation the rights > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > copies of the Software, and to permit persons to whom the Software is > furnished to do so, subject to the following conditions: > > The above copyright notice and this permission notice shall be included in > all copies or substantial portions of the Software. > > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > THE SOFTWARE. > """ > #-----------------\____________________________________/------------------ > > __author__ = 'Yaroslav Halchenko' > __revision__ = '$Revision: $' > __date__ = '$Date: $' > __copyright__ = 'Copyright (c) 2012 Yaroslav Halchenko' > __license__ = 'MIT' > > > import numpy as np > import pylab as pl > import scipy.stats as ss > > def plot_boxplot_enhanced( > v, > contrast_labels=None, > condition_labels=None, > ccolors=['y', 'b'], > rand_offsets=None, > grid=True, > xticks_rotation=0, > **bp_kwargs): > > width = bp_kwargs.get('width', 0.5) > pl.boxplot(v, **bp_kwargs) > > if v.ndim < 2: v = v[:, None] > ncol = v.shape[1] > > eff = np.mean(v, axis=0) # effect sizes > sem = ss.sem(v, axis=0) > > if rand_offsets is None: > rand_offsets = np.random.randn(len(v)) * 0.02 > > pl.plot((np.arange(ncol) + 1)[:, None] + rand_offsets, > v.T, '.', color='k', markerfacecolor='k') > for i in range(ncol): > lw = 2 > pl.plot([1 - width/2. + i, 1+i], > [0, 0], > '--', color=ccolors[0], linewidth=lw) # first condition > pl.plot([1+i, 1 + width/2. +i], > [eff[i]]*2, > '--', color=ccolors[1], linewidth=lw) > > # place ste > pl.errorbar(i+1 + 1.1*width/2., > eff[i], > sem[i], > elinewidth=2, linewidth=0, > color='r', ecolor='r') > > if contrast_labels and not i: # only for the first one > pl.text(1 - 1.1*width/2 + i, 0.1, contrast_labels[0], > verticalalignment='bottom', > horizontalalignment='right') > pl.text(1 + 1.2*width/2 + i, eff[i], contrast_labels[1], > verticalalignment='bottom', horizontalalignment='left') > ax = pl.gca() > if condition_labels: > ax.set_xticklabels(condition_labels, rotation=xticks_rotation) > else: > # hide it > ax.axes.xaxis.set_visible(False) > > if grid: > ax.grid() > return ax > > > def plot_paired_stats( > v0, v1, contrast_labels, > condition_labels=None, > style=['barplot_effect', > 'boxplot_raw', > 'boxplot_effect'], > ccolors=['y', 'g'], > xticks_rotation=0, > grid=False, > fig=None, > bottom_adjust=None, > bp_kwargs={}): > > if isinstance(style, str): > style = [style] > > nplots = len(style) # how many subplots will be needed > > # assure having 2nd dimension > if v0.ndim < 2: v0 = v0[:, None] > if v1.ndim < 2: v1 = v1[:, None] > assert(v0.shape == v1.shape) > > ncol = v0.shape[1] > v10 = (v1 - v0) # differences > mv0 = np.mean(v0, axis=0) # means > mv1 = np.mean(v1, axis=0) > > eff = np.mean(v10, axis=0) # effect sizes > sem = ss.sem(v10, axis=0) > > # so that data points have are distinguishable > rand_offsets = np.random.randn(len(v10)) * 0.02 > > # interleaved combination for some plots > v_ = np.hstack((v0, v1)) > v = np.zeros(v_.shape, dtype=v_.dtype) > v[:, np.hstack((np.arange(0, ncol*2, 2), > np.arange(1, ncol*2, 2)))] = v_ > > #print v.shape > #print np.mean(v0, axis=0), np.mean(v1, axis=0) > #print np.min(v10, axis=0), np.max(v10, axis=0), \ > # np.mean(v10, axis=0), ss.sem(v10, axis=0) > #pl.boxplot(v10 + np.mean(v1), notch=1, widths=0.05) > > #print v0.shape, v1.shape, np.hstack([v0, v1]).shape > > if fig is None: > fig = pl.figure() > > bwidth = 0.5 > plot = 1 > > if condition_labels: > xlabels = [ '%s:%s' % (cond, contr) > for cond in condition_labels > for contr in contrast_labels ] > else: > xlabels = contrast_labels > > bp_kwargs_ = { > #'bootstrap': 0, > 'notch' : 1 > } > bp_kwargs_.update(bp_kwargs) > > def plot_grid(ax): > if grid: > ax.grid() > > if 'barplot_effect' in style: > if len(style) > 1: > pl.subplot(1, nplots, plot) > plot += 1 > # The simplest one > pl.bar(np.arange(1, ncol*2+1) - bwidth/2, > np.mean(v, axis=0), > color=ccolors*ncol, > edgecolor=ccolors*ncol, > alpha=0.8, > width=bwidth) > #pl.minorticks_off() > pl.tick_params('x', direction='out', length=6, width=1, > top=False) > ax = pl.gca() > pl.xlim(0.5, ncol*2+0.5) > ax.set_xticks(np.arange(1, ncol*2+1)) > ax.set_xticklabels(xlabels, rotation=xticks_rotation) > # place ste for effect size into the 2nd column > pl.errorbar(np.arange(ncol)*2+2, > mv1, > sem, elinewidth=2, linewidth=0, > color='g', ecolor='r') > > plot_grid(ax) > > if 'boxplot_raw' in style: > if len(style) > 1: > pl.subplot(1, nplots, plot) > plot += 1 > > # Figure 1 -- "raw" data > # plot "connections" between boxplots > for i in range(ncol): > pargs = (np.array([i*2+1, i*2+2])[:, None] + rand_offsets, > np.array([v0[:,i], v1[:,i]])) > pl.plot(*(pargs+('-',)), color='k', alpha=0.5, linewidth=0.25) > pl.plot(*(pargs+('.',)), color='k', alpha=0.9) > # boxplot of "raw" data > bp1 = pl.boxplot(v, widths=bwidth, **bp_kwargs_) > for i in range(ncol): > for c in xrange(2): > b = bp1['boxes'][2*i+c] > b.set_color(ccolors[c]) > b.set_linewidth(2) > > ax = pl.gca() > ax.set_xticklabels(xlabels, rotation=xticks_rotation) > plot_grid(ax) > > if 'boxplot_effect' in style: > if len(style) > 1: > pl.subplot(1, nplots, plot) > plot += 1 > plot_boxplot_enhanced(v10, > contrast_labels=contrast_labels, > condition_labels=condition_labels, > widths=bwidth, > rand_offsets=rand_offsets, # reuse them > grid=grid, > **bp_kwargs_) > > if bottom_adjust: > fig.subplots_adjust(bottom=bottom_adjust) > pl.draw_if_interactive() > return fig > > if __name__ == '__main__': > > if True: > v = np.random.normal(size=(50,8)) * 20 + 120 > if False: > v[:, 1] += 40 > v[:, 3] -= 30 > v[:, 5] += 60 > v[:, 6] -= 60 > else: > v -= np.arange(v.shape[1])*10 > v /= 10 > > v0 = v[:, ::2] > v1 = v[:, 1::2] > d = v1 - v0 > print np.mean(d, axis=0) > styles = ['barplot_effect', > 'boxplot_raw', > 'boxplot_effect' > ] > styles = styles + [styles] > pl.close('all') > > if False: > f = plot_boxplot_enhanced((v1-v0)[:,0], > grid=True, xticks_rotation=30, notch=1) > > for s in styles: > fig = pl.figure(figsize=(12,6)) > f = plot_paired_stats(v0, v1, ['cont1', 'cont2'], > style=s, fig=fig, > condition_labels=['exp1', 'exp2', 'exp3', 'exp4'], > grid=True, xticks_rotation=30) > pl.show() > > > -- > Yaroslav O. Halchenko > Postdoctoral Fellow, Department of Psychological and Brain Sciences > Dartmouth College, 419 Moore Hall, Hinman Box 6207, Hanover, NH 03755 > Phone: +1 (603) 646-9834 Fax: +1 (603) 646-1419 > WWW: http://www.linkedin.com/in/yarik > > ------------------------------------------------------------------------------ > Monitor your physical, virtual and cloud infrastructure from a single > web console. Get in-depth insight into apps, servers, databases, vmware, > SAP, cloud infrastructure, etc. Download 30-day Free Trial. > Pricing starts from $795 for 25 servers or applications! > http://p.sf.net/sfu/zoho_dev2dev_nov > _______________________________________________ > Matplotlib-devel mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-devel |