抱歉,如果这篇文章有点冗长,但如果我缩短它,问题就会丢失。我正在尝试在pandas和matplotlib的基础上制作一个模块,使我能够制作类似于scatter_matrix的profile plots和profile matrices。我相当确定我的问题归结为需要从Profile()返回哪个对象,以便我可以在Profile_Matrix()中处理Axes操作。然后问题是从Profile_Matrix()返回什么,以便我可以编辑子图。
我的模块(ProfileModule.py)很大程度上借鉴了https://github.com/pydata/pandas/blob/master/pandas/tools/plotting.py,看起来像:
这应该会生成一个简单的个人资料图和3x3个人资料矩阵,但事实并非如此。我尝试了各种不同的方法来使其工作,但我想解释它们都不值得。
我应该提到我在Windows 7上使用Enthought Canopy Express。抱歉发了这么长的帖子,再次感谢您对代码的任何帮助。这是我使用Python的第一周。
我的模块(ProfileModule.py)很大程度上借鉴了https://github.com/pydata/pandas/blob/master/pandas/tools/plotting.py,看起来像:
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
这将类似于以下方式运行:
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个人资料矩阵,但事实并非如此。我尝试了各种不同的方法来使其工作,但我想解释它们都不值得。
我应该提到我在Windows 7上使用Enthought Canopy Express。抱歉发了这么长的帖子,再次感谢您对代码的任何帮助。这是我使用Python的第一周。
fig
,你总是可以通过fig.axes
访问轴,而且如果你想要调整整个图形的大小或其他什么操作,你也需要它。 - Javier