2012-01-17 5 views
1

私はPythonとmatplotlibを使用して、 が複雑な図形を生成するカスタムクラスを定義しようとしています。しかし、私は ボックスプロットを正しく印刷するのに問題があります。ウィスカーなしで表示され続けるか、または中央値を示す 行が表示され続けます。私はサンプル画像を埋め込むことはできませんが、あなたはsee one hereです。オブジェクト指向のmatplotlibを使用するとウィスカーやメジアンのないボックスプロットが奇妙に生成される

from numpy.random import randn 
import mycustomfigures as hf 
test_x = np.arange(0, 25, 0.01) 
test_y = test_x + randn(2500) 
test_data = zip(test_x, test_y) 
test_fig = hf.DotDashHist(test_data) 
test_fig.makebox() 
test_fig.suptitle('Test Figure') 
test_fig.savefig('testing.svg') 

私はDotDashHist定義した方法の何が問題なのです:

import matplotlib as mpl 
import matplotlib.pyplot as plt 
from matplotlib.ticker import FixedLocator 
from matplotlib.gridspec import GridSpec 
from matplotlib.figure import Figure 
from matplotlib.backends.backend_svg import FigureCanvasSVG as FigureCanvas 
import numpy as np 
import scipy as sp 
import scipy.optimize 

class DotDashHist(Figure): 
    """A Tufte-style dot-dash plot with histograms along the x- and y-axes.""" 
    def __init__(self, the_vals): 
     # Actually inherit all the attributes and methods of parent class 
     super(DotDashHist, self).__init__() 
     # Process incoming data 
     self.vals = the_vals 
     self.xvals, self.yvals = zip(*self.vals) 
     self.xvals_uniq = list(set(self.xvals)) 
     self.yvals_uniq = list(set(self.yvals)) 
     self.xmax = float(max(self.xvals_uniq)) 
     self.xpadding = float(self.xmax/50) 
     self.ymax = float(max(self.yvals_uniq)) 
     self.ypadding = float(self.ymax/50) 
     self.xlims = [-1 * self.xpadding, self.xmax + self.xpadding] 
     self.ylims = [-1 * self.ypadding, self.ymax + self.ypadding] 
     self.lims = [-1 * self.xpadding, self.xmax + self.xpadding, 
        -1 * self.ypadding, self.ymax + self.ypadding] 
     # Set some matplotlib default behavior 
     mpl.rcParams['backend'] = 'SVG' 
     mpl.rcParams['lines.antialiased'] = True 
     mpl.rcParams['font.family'] = 'sans-serif' 
     mpl.rcParams['font.sans-serif'] = 'Gill Sans MT Pro, Lucida Grande, Helvetica, sans-serif' 
     mpl.rcParams['axes.titlesize'] = 'large' 
     mpl.rcParams['axes.labelsize'] = 'xx-small' 
     mpl.rcParams['xtick.major.size'] = 2 
     mpl.rcParams['xtick.minor.size'] = 0.5 
     mpl.rcParams['xtick.labelsize'] = 'xx-small' 
     mpl.rcParams['ytick.major.size'] = 2 
     mpl.rcParams['ytick.minor.size'] = 0.5 
     mpl.rcParams['ytick.labelsize'] = 'xx-small' 
    def _makeskel(self): 
     # Set up the framework in which the figure will be drawn 
     # Define the canvas for the figure 
     self.canvas = FigureCanvas(self) 
     self.set_canvas(self.canvas) 
     # Place subplots on a 6x6 grid 
     gs = GridSpec(6,6) 
     # Add the main subplot, override weird axis and tick defaults 
     self.main = self.add_subplot(gs[1:, :-1]) 
     self.main.set_frame_on(False) 
     self.main.get_xaxis().tick_bottom() 
     self.main.get_yaxis().tick_left() 
     self.main.axis(self.lims) 
     # Add the x-value histogram, override weird axis and tick defaults 
     self.xhist = self.add_subplot(gs[0, :-1]) 
     self.xhist.set_xticks([]) 
     self.xhist.set_yticks([]) 
     self.xhist.set_frame_on(False) 
     self.xhist.get_xaxis().tick_bottom() 
     self.xhist.get_yaxis().tick_left() 
     self.xhist.set_xlim(self.xlims) 
     # Add the y-value histogram, override weird axis and tick defaults 
     self.yhist = self.add_subplot(gs[1:, -1]) 
     self.yhist.set_xticks([]) 
     self.yhist.set_yticks([]) 
     self.yhist.set_frame_on(False) 
     self.yhist.get_xaxis().tick_bottom() 
     self.yhist.get_yaxis().tick_left() 
     self.yhist.set_ylim(self.ylims) 
    def _makehist(self): 
     # Draw the x- and y-value histograms 
     self.xhist.hist(self.xvals, normed=1, bins=min([50, self.xmax + 1]), 
         range=[0, self.xmax + self.xpadding]) 
     self.yhist.hist(self.yvals, normed=1, bins=min([50, self.ymax + 1]), 
         range=[0, self.ymax + self.ypadding], 
         orientation='horizontal') 
    def makebox(self): 
     self._makeskel() 
     self._makehist() 
     # Aggregate to make boxplots 
     box_dict = {} 
     for point in self.vals: 
      if point[0] <= self.xmax and point[1] <= self.ymax: 
       box_dict.setdefault(round(float(point[0]), 0), 
         []).append(point[1]) 
     self.main.boxplot(box_dict.values(), positions=box_dict.keys(), 
       whis=1.0, sym='ro') 
     self.main.set_xticks(np.arange(0, self.xmax + 1, 12)) 
     self.main.xaxis.set_minor_locator(FixedLocator(self.xvals_uniq)) 
     self.main.yaxis.set_minor_locator(FixedLocator(self.yvals_uniq)) 

このテストコードは、問題が表示されます。次のように

マイカスタムクラスが定義されていますか?私は、MATLABスタイルのステートフルな構文を使用してウィスカー付きボックスプロットを作成することができますが、そのアプローチは複数の図を描くときに膨大な量のコードを生成します。

+0

私は理解していない:任意のレートで

、私はもう少し、このように進むだろうか? –

+0

私はPythonには比較的新しいので、matplotlibの学習を始めました。私が言うことは、それは私には分かりやすいようだということです。私は3つのサブプロットで図を生成しようとしているので、Figureをサブクラス化しました。これを行うより賢明な方法がありますか? – akshayshah

+1

さて、それのためにFigureをサブクラス化する正当な理由はありません(あなたはそうすることができますが)。スタンドアローンのクラスを作成し、Figureインスタンスを 'self.fig'として開始するほうが、おそらくもっと冗長になるでしょう。 –

答えて

3

ウィスカは私の元々のプロットに含まれていますが、あなたがプロットしたアウトライアポイントによってはっきりとわかりません。あなたはこのために `Figure`をサブクラス化している理由

import collections 
import matplotlib.pyplot as plt 
from matplotlib.gridspec import GridSpec 
import numpy as np 

def main(): 
    x = np.arange(0, 25, 0.01) 
    y = x + np.random.randn(x.size) 
    plot = DotDashHist(figsize=(10, 8)) 
    plot.plot(x, y, whis=1.0, sym='r.') 
    plot.title('This is a Test') 
    plt.show() 

class DotDashHist(object): 
    def __init__(self, **kwargs): 
     self.fig = plt.figure(**kwargs) 
     gs = GridSpec(6, 6) 
     self.ax = self.fig.add_subplot(gs[1:, :-1]) 
     self.topax = self.fig.add_subplot(gs[0, :-1], sharex=self.ax) 
     self.rightax = self.fig.add_subplot(gs[1:, -1], sharey=self.ax) 
     for ax in [self.topax, self.rightax]: 
      ax.set_axis_off() 

    def plot(self, x, y, **kwargs): 
     _, _, self.topbars = self.topax.hist(x, normed=1, bins=50) 
     _, _, self.rightbars = self.rightax.hist(y, normed=1, bins=50, 
               orientation='horizontal') 
     boxes = collections.defaultdict(list) 
     for X, Y in zip(x, y): 
      boxes[int(X)].append(Y) 

     kwargs.pop('positions', None) 
     self.boxes = self.ax.boxplot(boxes.values(), **kwargs) 

    def title(self, *args, **kwargs): 
     self.topax.set_title(*args, **kwargs) 

if __name__ == '__main__': 
    main() 

enter image description here

+0

ありがとう、ジョー - フライングポイントをオフにしても、元のコードでウィスカーを取得できませんでした。あなたのソリューションは完璧に動作しますが、それはずっと短くなっています! – akshayshah

+0

ええええええええええええええええええ...それは多分matplotlibのバージョンの問題ですか?いずれにせよ、私の例があなたのために働いてうれしいです! –

+0

私はそれが私のSVGバックエンドの問題だと思います - どちらのバージョンもAggバックエンドと対話型ディスプレイでうまく動作しますが、どちらもSVGで動作しません。 SVGは重要ではないので、私はあなたの例をインスピレーションとして取り上げ、そこから行くつもりです。再度、感謝します... – akshayshah

関連する問題