如何在matplotlib图中添加轴偏移量?

发布于 2021-01-29 14:56:56

我在同一张图上绘制了多个seaborn点图。x轴是序数,而不是数字。每个点图的序数值都相同。我想将每个图稍微移到一边,pointplot(dodge =
…)参数的方式是在单个图内的多条线内进行,但是在这种情况下,是要在彼此之上绘制多个不同图。我怎样才能做到这一点?

理想情况下,我想要一种适用于任何matplotlib图的技术,而不仅仅是专门针对海洋的技术。由于数据不是数字,因此很难为数据添加偏移量。

显示地块重叠并使其难以阅读的示例(每个地块内的闪避都可以)

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。

关注者
0
被浏览
115
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    首先回答最常见的情况。可以通过将图中的艺术家移动一定量来实现躲避。将点用作该偏移的单位可能会很有用。例如,您可能需要将情节上的标记移动5点。
    可以通过在艺术家的数据转换中添加翻译来完成此转换。我在这里提出一个建议ScaledTranslation

    现在,为了保持最通用,可以编写一个函数,该函数将绘图方法,轴和数据作为输入,此外还应应用一些闪避功能,例如

    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功能等,因为他们没有任何有用的艺术家复工用。


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

    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()
    

    在此处输入图片说明



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看