Python 在matplotlib中实现地平线图
我正在尝试在matplotlib中实现地平线图(请参阅:) 其基本思想是以窄纵横比显示时间序列,随着值的增加(超过y轴限制),它们从底部开始以较暗的颜色显示(想象一下旧的Atari游戏,当你越过屏幕顶部,从底部弹出) 我的基本方法是使用Python 在matplotlib中实现地平线图,python,matplotlib,Python,Matplotlib,我正在尝试在matplotlib中实现地平线图(请参阅:) 其基本思想是以窄纵横比显示时间序列,随着值的增加(超过y轴限制),它们从底部开始以较暗的颜色显示(想象一下旧的Atari游戏,当你越过屏幕顶部,从底部弹出) 我的基本方法是使用ax.twinx()将y数据划分为卡盘,并在新轴上绘制每个垂直组,并适当设置限制 仅就正面或负面数据而言,这似乎效果良好 肯定的: 否定: 但出于某种原因,这两种方法都会出错: # setup the environment import numpy as n
ax.twinx()
将y数据划分为卡盘,并在新轴上绘制每个垂直组,并适当设置限制
仅就正面或负面数据而言,这似乎效果良好
肯定的:
否定:
但出于某种原因,这两种方法都会出错:
# setup the environment
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, np.pi*4, 137)
y = (2*np.random.normal(size=137) + x**2)
# reflect everything around the origin
xx = np.hstack([-1*x[::-1], x])
yy = np.hstack([-1*y[::-1], y])
# function to do the plot
def horizonPlot(ax, x, y, nfolds=3, inverty=False, color='CornflowerBlue'):
axes = [ax]
if inverty:
ylims = np.linspace(y.min(), y.max(), nfolds + 1)[::-1]
else:
ylims = np.linspace(y.min(), y.max(), nfolds + 1)
for n in range(1, nfolds):
newax = axes[-1].twinx()
axes.append(newax)
for n, ax in enumerate(axes):
ax.fill_between(x, y, y2=ylims[n], facecolor=color, alpha=1.0/nfolds, zorder=n)
ax.set_ylim([ylims[n], ylims[n+1]])
ax.set_yticklabels([])
ax.set_yticks([])
if inverty:
ax.invert_yaxis()
ax.set_xlim([x.min(), x.max()])
return fig
fig, baseax = plt.subplots(figsize=(6.5,1.5))
posax = baseax.twinx()
negax = posax.twinx()
fig = horizonPlot(posax, xx, np.ma.masked_less(yy, 0), inverty=False, color='DarkGreen')
fig = horizonPlot(negax, xx, np.ma.masked_greater(yy, 0), inverty=True, color='CornflowerBlue')
for ax in fig.get_axes():
ax.set_yticklabels([])
fig.tight_layout()
plt.show()
坏图表(注意正面缺少多个图层):
任何想法都将不胜感激 我实际上不知道,为什么你的电脑不工作,因为在我的电脑上它工作得很好。但是,由于我对这个绘图非常感兴趣,我尝试自己实现它,而不需要所有这些花哨的
twinx
东西
我只是把这些区域画在彼此的上面,因为这实际上是这个图的一大优点。因此,我不需要调整alpha,它们只是相加
import numpy as np
from matplotlib.pyplot import *
def layer(y,height):
neg=0.0;pos=0.0
if y>0:
if y-height>=0:
pos=height
y-= pos
else :
pos = y
elif y<0:
if y+height<=0:
neg=height
y += neg
else :
neg = -y
return pos,neg
def horizonPlot(x,y,height=50.0,colors=['CornflowerBlue','DarkGreen']):
alpha = .10
vlayer = np.vectorize(layer)
while (y != 0).any():
l = vlayer(y,height)
y -= l[0];y += l[1]
fill_between(x,0,l[0],color=colors[0], alpha=alpha)
fill_between(x,height-l[1],height,color=colors[1], alpha=alpha)
def main():
x = np.linspace(0, np.pi*4, 137)
y = (2*np.random.normal(size=137) + x**2)
xx = np.hstack([-1*x[::-1], x])
yy = np.hstack([-1*y[::-1], y])
horizonPlot(xx,yy)
show()
将numpy导入为np
从matplotlib.pyplot导入*
def层(y,高度):
负=0.0;pos=0.0
如果y>0:
如果y高度>=0:
pos=高度
y-=位置
其他:
pos=y
伊莱夫·易也想到了实施立体主义。我一定会在代码运行后立即使用它;已经非常感谢了。您能解释一下zstart
参数的作用吗?当我在我的机器上运行这个时,它看起来更糟糕,更高的层被绘制在它抛出的图表之外紧密布局:返回到Agg渲染器@MillaWell-whoops,这是一个失败实验留下的残留kwarg。我认为Zorder应该受到某种程度的责备,所以zstart允许我确保消极层和积极层彼此远离。我只想说,这没有帮助,我已经把它从帖子中删除了。至于Agg回退——注释掉调用fig.tight\u layout
。这有帮助吗?确实有帮助,事实上:你能告诉我你的“坏图表”有什么问题吗?如果唯一的错误是绿色层没有相互标绘,那么这在我的机器上可以正常工作!你有没有试着评论一下紧凑的布局@米拉威尔:是的,问题是分层在积极的方面失败了。基本上,我希望前两张图表叠在一起。好吧,那么对我来说似乎有效=)你愿意发布这段代码吗,或者你介意我使用它吗?谢谢。这在我的MPL1.2系统上运行。有趣的是,这两种实现都在MPL1.1上工作。希望我能抽出时间做一次git对分,找出差异所在。另外,我对您的实现进行了改进。值得一提的是,所有高于v1.2.1的matplotlib更高版本都修复了此问题。此实现存在一些问题。Tryy=np.array([0100,-100100,0]).T;水平图(范围(5),y)
-问题是必须在穿过轴的每对y值之间添加一个x值。