【问题标题】:matplotlib boxplot doesn't align with overlaid scatterplotmatplotlib boxplot 与覆盖散点图不对齐
【发布时间】:2021-10-27 15:49:45
【问题描述】:

我有一个情节,我试图在箱线图系列上叠加一个散点系列......这是一个简单的问题示例,以便您可以重新创建它。

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

names = ['a','b','c','d','e','f']

df = pd.DataFrame(np.random.rand(6,6), columns=names)
display(df)

plt.boxplot(df, labels=names)
plt.show()

plt.scatter(names, df.head(1))
plt.show()

plt.boxplot(df, labels=names)
plt.scatter(names, df.head(1))
plt.show()

结果:

所以您会看到,当箱线图和散点图都添加到同一个图中时,标签不再正确对齐。如何修复这种对齐方式?

【问题讨论】:

    标签: python pandas matplotlib scatter-plot boxplot


    【解决方案1】:
    • python 3.8.11pandas 1.3.2matplotlib 3.4.3seaborn 0.11.2 中测试
    • 请注意xticklabel 位置未对齐。
    • 根据matplotlib.pyplot.boxplotposition 默认为range(1, N+1)
    fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(6, 8))
    ax1.boxplot(df, labels=names)
    print(ax1.get_xticks())
    ax2.scatter(names, df.head(1))
    print(ax2.get_xticks())
    
    ax3.boxplot(df, labels=names)
    ax3.scatter(names, df.head(1))
    [out]:
    [1 2 3 4 5 6]
    [0, 1, 2, 3, 4, 5]
    

    • 根据现有代码,正确的解决方案是设置positions 参数
    • 这还需要将数据帧转换为带有pandas.DataFrame.melt 的长格式,用于散点图。
    plt.boxplot(df, labels=names, positions=range(len(df.columns)))
    plt.scatter(data=df.melt(), x='variable', y='value')
    

    ax = df.plot(kind='box', positions=range(len(df.columns)))
    df.melt().plot(kind='scatter', x='variable', y='value', ax=ax)
    

    import seaborn as sns
    
    sns.boxplot(data=df, boxprops={'facecolor':'None'})
    print(plt.xticks())
    sns.swarmplot(data=df)
    print(plt.xticks())
    
    [out]:
    (array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])
    (array([0, 1, 2, 3, 4, 5]), [Text(0, 0, 'a'), Text(1, 0, 'b'), Text(2, 0, 'c'), Text(3, 0, 'd'), Text(4, 0, 'e'), Text(5, 0, 'f')])
    

    【讨论】:

    • 伙计,你刚刚救了我,你提出的解决方案效果很好! :)
    【解决方案2】:

    传递给 scatter 的数据的形状不正确,需要移动索引,因为箱线图索引从 1 开始。

    这是一个可行的解决方案:

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    
    names = ['a','b','c','d','e','f']
    
    df = pd.DataFrame(np.random.rand(6,6), columns=names)
    display(df)
    
    plt.boxplot(df, labels=names)
    plt.show()
    
    df2 = df.copy()
    df2.columns = range(1, len(df2.columns)+1)
    df2 = df2.unstack().reset_index(level=0)
    
    plt.scatter(*df2.values.T)
    plt.show()
    
    plt.boxplot(df, labels=names)
    plt.scatter(*df2.values.T)
    plt.show()
    

    需要给scatter提供什么:

    [1., 1., 1., 1., 1., 1., 2., 2., 2., 2., 2., 2., 3., 3., 3., 3., 3.,
    3., 4., 4., 4., 4., 4., 4., 5., 5., 5., 5., 5., 5., 6., 6., 6., 6.,
    6., 6.]
    

    [0.40196123, 0.24802927, 0.3152357 , 0.76739054, 0.06847434,
    0.30173798, 0.30350823, 0.36324843, 0.35928768, 0.69194326,
    0.61586685, 0.74039024, 0.56971769, 0.37970524, 0.67049866,
    0.82031296, 0.15917911, 0.58760412, 0.02660848, 0.67014213,
    0.46027398, 0.39161172, 0.01191327, 0.48197714, 0.79882359,
    0.84189102, 0.10873758, 0.56858526, 0.48169526, 0.08860958,
    0.43500853, 0.26380151, 0.14911615, 0.47846386, 0.25583401,
    0.04949216]
    

    【讨论】:

      猜你喜欢
      • 2015-11-30
      • 1970-01-01
      • 2017-06-22
      • 2014-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-17
      • 2020-06-12
      相关资源
      最近更新 更多