如何在 matplotlib 图中添加轴偏移量? [英] How to add axis offset in matplotlib plot?

查看:74
本文介绍了如何在 matplotlib 图中添加轴偏移量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在同一张图上绘制了Seaborn中的几个点图.x轴是序数,而不是数字.每个点图的序数值都相同.我想将每个图向一侧移动一点,pointplot(dodge=...) 参数在单个图中的多行内执行的方式,但在这种情况下,对于绘制在彼此之上的多个不同图.我该怎么做?

I'm drawing several point plots in seaborn on the same graph. The x-axis is ordinal, not numerical; the ordinal values are the same for each point plot. I would like to shift each plot a bit to the side, the way pointplot(dodge=...) parameter does within multiple lines within a single plot, but in this case for multiple different plots drawn on top of each other. How can I do that?

理想情况下,我想要一种适用于任何matplotlib图的技术,而不仅仅是专门针对seaplotlib.向数据添加偏移量并不容易,因为数据不是数字.

Ideally, I'd like a technique that works for any matplotlib plot, not just seaborn specifically. Adding an offset to the data won't work easily, since the data is not numerical.

显示情节重叠并使其难以阅读的示例(在每个情节内躲避可以正常工作)

Example that shows the plots overlapping and making them hard to read (dodge within each plot works okay)

import pandas as pd
import seaborn as sns

df1 = pd.DataFrame({'x':list('ffffssss'), 'y':[1,2,3,4,5,6,7,8], 'h':list('abababab')})
df2 = df1.copy()
df2['y'] = df2['y']+0.5
sns.pointplot(data=df1, x='x', y='y', hue='h', ci='sd', errwidth=2, capsize=0.05, dodge=0.1, markers='<')
sns.pointplot(data=df2, x='x', y='y', hue='h', ci='sd', errwidth=2, capsize=0.05, dodge=0.1, markers='>')

我可以使用seaborn以外的其他工具,但是自动置信度/错误栏非常方便,因此我宁愿在这里坚持使用seaborn.

I could use something other than seaborn, but the automatic confidence / error bars are very convenient so I'd prefer to stick with seaborn here.

推荐答案

首先针对最一般的情况回答这个问题.可以通过将图中的艺术家移动一定量来实现躲避.将点用作该偏移的单位可能会很有用.例如.您可能希望将绘图上的标记移动 5 个点.
这种转变可以通过向艺术家的数据转换添加转换来完成.这里我推荐一个ScaledTranslation.

Answering this for the most general case first. A dodge can be implemented by shifting the artists in the figure by some amount. It might be useful to use points as units of that shift. E.g. you may want to shift your markers on the plot by 5 points.
This shift can be accomplished by adding a translation to the data transform of the artist. Here I propose a ScaledTranslation.

现在要保持这种通用性,可以编写一个函数,该函数将绘图方法,轴和数据作为输入,此外还应加上一些闪避,例如

Now to keep this most general, one may write a function which takes the plotting method, the axes and the data as input, and in addition some dodge to apply, e.g.

draw_dodge(ax.errorbar, X, y, yerr =y/4., ax=ax, dodge=d, marker="d" )

完整功能代码:

import matplotlib.pyplot as plt
from matplotlib import transforms
import numpy as np
import pandas as pd


def draw_dodge(*args, **kwargs):
    func = args[0]
    dodge = kwargs.pop("dodge", 0)
    ax = kwargs.pop("ax", plt.gca())
    trans = ax.transData  + transforms.ScaledTranslation(dodge/72., 0,
                                   ax.figure.dpi_scale_trans)
    artist = func(*args[1:], **kwargs)
    def iterate(artist):
        if hasattr(artist, '__iter__'):
            for obj in artist:
                iterate(obj)
        else:
            artist.set_transform(trans)
    iterate(artist)
    return artist

X = ["a", "b"]
Y = np.array([[1,2],[2,2],[3,2],[1,4]])

Dodge = np.arange(len(Y),dtype=float)*10
Dodge -= Dodge.mean()

fig, ax = plt.subplots()

for y,d in zip(Y,Dodge):
    draw_dodge(ax.errorbar, X, y, yerr =y/4., ax=ax, dodge=d, marker="d" )

ax.margins(x=0.4)
plt.show()

您可以将其与 ax.plotax.scatter 等一起使用.但不能与任何 seaborn 函数一起使用,因为它们不会返回任何有用的艺术家与之共事.

You may use this with ax.plot, ax.scatter etc. However not with any of the seaborn functions, because they don't return any useful artist to work with.

对于所讨论的情况,剩下的问题是以有用的格式获取数据.一种选择如下.

Now for the case in question, the remaining problem is to get the data in a useful format. One option would be the following.

df1 = pd.DataFrame({'x':list('ffffssss'), 
                    'y':[1,2,3,4,5,6,7,8], 
                    'h':list('abababab')})
df2 = df1.copy()
df2['y'] = df2['y']+0.5

N = len(np.unique(df1["x"].values))*len([df1,df2])
Dodge = np.linspace(-N,N,N)/N*10


fig, ax = plt.subplots()
k = 0
for df in [df1,df2]:
    for (n, grp) in df.groupby("h"):
        x = grp.groupby("x").mean()
        std = grp.groupby("x").std()
        draw_dodge(ax.errorbar, x.index, x.values, 
                   yerr =std.values.flatten(), ax=ax, 
                   dodge=Dodge[k], marker="o", label=n)
        k+=1

ax.legend()        
ax.margins(x=0.4)
plt.show()

这篇关于如何在 matplotlib 图中添加轴偏移量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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