我应该如何通过函数传递matplotlib对象;作为轴,轴还是图形? [英] How should I pass a matplotlib object through a function; as Axis, Axes or Figure?

查看:266
本文介绍了我应该如何通过函数传递matplotlib对象;作为轴,轴还是图形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起,如果这有点缠绵,但是如果我把它切得太多的话,问题就不复存在了.我正在尝试在pandas和matplotlib之上制作一个模块,这将使我能够制作类似于scatter_matrix的轮廓图和轮廓矩阵.我很确定我的问题归结于我需要从Profile()返回的对象,以便可以处理Profile_Matrix()中的轴操作.然后的问题是,要从Profile_Matrix()返回什么,以便我可以编辑子图.

Sorry in advance if this is a little long winded but if I cut it down too much the problem is lost. I am trying to make a module on top of pandas and matplotlib which will give me the ability to make profile plots and profile matrices analogous to scatter_matrix. I am pretty sure my problem comes down to what object I need to return from Profile() so that I can handle Axes manipulation in Profile_Matrix(). Then the question is what to return form Profile_Matrix() so I can edit subplots.

我的模块(ProfileModule.py)从 https借来了很多东西://github.com/pydata/pandas/blob/master/pandas/tools/plotting.py 如下:

My module (ProfileModule.py) borrows a lot from https://github.com/pydata/pandas/blob/master/pandas/tools/plotting.py and looks like:

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
import matplotlib.pyplot as plt

def Profile(x,y,nbins,xmin,xmax):
    df = DataFrame({'x' : x , 'y' : y})

    binedges = xmin + ((xmax-xmin)/nbins) * np.arange(nbins+1)
    df['bin'] = np.digitize(df['x'],binedges)

    bincenters = xmin + ((xmax-xmin)/nbins)*np.arange(nbins) + ((xmax-xmin)/(2*nbins))
    ProfileFrame = DataFrame({'bincenters' : bincenters, 'N' : df['bin'].value_counts(sort=False)},index=range(1,nbins+1))

    bins = ProfileFrame.index.values
    for bin in bins:
        ProfileFrame.ix[bin,'ymean'] = df.ix[df['bin']==bin,'y'].mean()
        ProfileFrame.ix[bin,'yStandDev'] = df.ix[df['bin']==bin,'y'].std()
        ProfileFrame.ix[bin,'yMeanError'] = ProfileFrame.ix[bin,'yStandDev'] / np.sqrt(ProfileFrame.ix[bin,'N'])

    fig = plt.figure(); 
    ax = ProfilePlot.add_subplot(1, 1, 1)
    plt.errorbar(ProfileFrame['bincenters'], ProfileFrame['ymean'], yerr=ProfileFrame['yMeanError'], xerr=(xmax-xmin)/(2*nbins), fmt=None)

    return ax
    #or should I "return fig"


def Profile_Matrix(frame):

    import pandas.core.common as com
    import pandas.tools.plotting as plots
    from pandas.compat import lrange
    from matplotlib.artist import setp

    range_padding=0.05


    df = frame._get_numeric_data()
    n = df.columns.size

    fig, axes = plots._subplots(nrows=n, ncols=n, squeeze=False)

    # no gaps between subplots
    fig.subplots_adjust(wspace=0, hspace=0)

    mask = com.notnull(df)

    boundaries_list = []
    for a in df.columns:
        values = df[a].values[mask[a].values]
        rmin_, rmax_ = np.min(values), np.max(values)
        rdelta_ext = (rmax_ - rmin_) * range_padding / 2.
        boundaries_list.append((rmin_ - rdelta_ext, rmax_+ rdelta_ext))

    for i, a in zip(lrange(n), df.columns):
        for j, b in zip(lrange(n), df.columns):
            ax = axes[i, j]
            common = (mask[a] & mask[b]).values
            nbins = 100
            (xmin,xmax) = boundaries_list[i]

            ax=Profile(df[b][common],df[a][common],nbins,xmin,xmax)
            #Profile(df[b][common].values,df[a][common].values,nbins,xmin,xmax)

            ax.set_xlabel('')
            ax.set_ylabel('')

            plots._label_axis(ax, kind='x', label=b, position='bottom', rotate=True)
            plots._label_axis(ax, kind='y', label=a, position='left')

            if j!= 0:
                ax.yaxis.set_visible(False)
            if i != n-1:
                ax.xaxis.set_visible(False)

    for ax in axes.flat:
        setp(ax.get_xticklabels(), fontsize=8)
        setp(ax.get_yticklabels(), fontsize=8)

    return axes

这将与以下内容一起运行:

This will run with something like:

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
import matplotlib.pyplot as plt

import ProfileModule as pm

x = np.random.uniform(0, 100, size=1000)
y = x *x  +  50*x*np.random.randn(1000)
z = x *y  +  50*y*np.random.randn(1000)

nbins = 25
xmax = 100
xmin = 0

ProfilePlot = pm.Profile(x,y,nbins,xmin,xmax)
plt.title("Look this works!")

#This does not work as expected
frame = DataFrame({'z' : z,'x' : x , 'y' : y})
ProfileMatrix = pm.Profile_Matrix(frame)
plt.show()

希望这会产生一个简单的轮廓图和一个3x3的轮廓矩阵,但事实并非如此.我尝试了各种不同的方法来使它起作用,但我想不值得一一解释.

This would hopefully produce a simple profile plot and a 3x3 profile matrix but it does not. I have tried various different methods to get this to work but I imagine it is not worth explaining them all.

我应该提到我在Windows 7上使用Enthought Canopy Express.很抱歉,冗长的帖子,再次感谢您对代码的任何帮助.这是我使用Python的第一周.

I should mention I am using Enthought Canopy Express on Windows 7. Sorry for the long post and thanks again for any help with the code. This is my first week using Python.

推荐答案

您应该传递Axes对象,并分解功能以一次在单个轴上进行操作.您很亲密,但只需更改

You should pass around Axes objects and break your functions up to operate on a single axes at a time. You are close, but just change

import numpy as np
import matplotlib.pyplot as plt

def _profile(ax, x, y):
    ln, = ax.plot(x, y)
    # return the Artist created
    return ln


def profile_matrix(n, m):
    fig, ax_array = plt.subplots(n, m, sharex=True, sharey=True)
    for ax in np.ravel(ax_array):
        _profile(ax, np.arange(50), np.random.rand(50))

profile_matrix(3, 3)

这篇关于我应该如何通过函数传递matplotlib对象;作为轴,轴还是图形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆