【问题标题】:Pandas plot does not overlay熊猫图不叠加
【发布时间】:2017-03-22 10:13:34
【问题描述】:

我正在尝试用如下示例中的折线图覆盖堆积条形图,但只显示了第二个图,无法理解原因。

import pandas as pd
from matplotlib import pyplot as plt
df=pd.DataFrame({'yarding, mobile cable yarder on trailer': {1928: 1.4027824821879459e-20, 1924: 3.4365045943961052e-37, 1925: 6.9939032596152882e-30, 1926: 1.0712940173393567e-25, 1927: 8.6539917152671678e-23},
                 'yarding and processing, mobile cable yarder on truck': {1928: 1.1679873528237404e-20, 1924: 2.8613089094435456e-37, 1925: 5.8232768671842113e-30, 1926: 8.9198283644271726e-26, 1927: 7.2055027953028907e-23},
                 'delimbing, with excavator-based processor': {1928: 1.6998969986716558e-20, 1924: 4.1643685881703105e-37, 1925: 8.4752370448040848e-30, 1926: 1.2981979323251926e-25, 1927: 1.0486938381883222e-22}})
df2=pd.Series({1928: 3.0638184091973243e-19, 1924: 7.5056562764093482e-36, 1925: 1.5275356821475311e-28, 1926: 2.3398091372066067e-24, 1927: 1.8901157781841223e-21})

ax=df.plot(kind='bar',stacked=True,legend=False)
df2.plot(kind='line',ax=ax)
plt.show()

【问题讨论】:

  • 您看不到条形,因为它的最大值为 4.5 x 10^-20。
  • 我曾尝试做 df=df*1e+26 和 df2=df2*1e+26 作为测试,但问题仍然存在。无论如何,如果我分别绘制两个数据框是可以的,问题是它们不重叠

标签: python pandas matplotlib


【解决方案1】:

线图将数值数据相互对照。
条形图根据分类数据绘制数值数据。因此,即使条形图中的 x 值是数字,绘制它们的比例也不对应于这些数字,而是对应于某个索引。

这意味着条形图的 x 轴刻度总是从 0 到 N,其中 N 是条形的数量(粗略地说,实际上它是 -0.5 到 N-0.5)。

如果您现在将 1000 以上范围内的一些值添加到该比例,条形将缩小,直到它们不再可见(因此您可能认为它们甚至不存在)。

为了避免这个问题,您可以在两个不同的轴上工作。一个用于线图,一个用于条形图,但它们共享相同的 y 轴。

以下是一个可能的解决方案(与 Martin 的解决方案非常相似,他在我输入此内容时添加了该解决方案):

import pandas as pd
from matplotlib import pyplot as plt
df=pd.DataFrame({'yarding, mobile cable yarder on trailer': {1928: 1.4027824821879459e-20, 1924: 3.4365045943961052e-37, 1925: 6.9939032596152882e-30, 1926: 1.0712940173393567e-25, 1927: 8.6539917152671678e-23},
                 'yarding and processing, mobile cable yarder on truck': {1928: 1.1679873528237404e-20, 1924: 2.8613089094435456e-37, 1925: 5.8232768671842113e-30, 1926: 8.9198283644271726e-26, 1927: 7.2055027953028907e-23},
                 'delimbing, with excavator-based processor': {1928: 1.6998969986716558e-20, 1924: 4.1643685881703105e-37, 1925: 8.4752370448040848e-30, 1926: 1.2981979323251926e-25, 1927: 1.0486938381883222e-22}})
df2=pd.Series({1928: 3.0638184091973243e-19, 1924: 7.5056562764093482e-36, 1925: 1.5275356821475311e-28, 1926: 2.3398091372066067e-24, 1927: 1.8901157781841223e-21})

fig, ax = plt.subplots()
# optionally make log scale
ax.set_yscale("log", nonposy='clip')
# create shared y axes
ax2 = ax.twiny()
df.plot(kind='bar',stacked=True,legend=False, ax=ax)
df2.plot(kind='line',ax=ax2)
ax2.xaxis.get_major_formatter().set_useOffset(False)
# remove upper axis ticklabels
ax2.set_xticklabels([])
# set the limits of the upper axis to match the lower axis ones
ax2.set_xlim(1923.5,1928.5)
plt.show()

【讨论】:

    【解决方案2】:

    ImportanceOfBeingErnest 的回答中已经解释了潜在的问题。您可以通过在pandas line plot 中设置参数use_index=False 来解决它,这将使线图使用与条形图相同的x 轴单位。不需要任何 matplotlib 函数:

    import pandas as pd    # v 1.1.3
    
    df = pd.DataFrame({'yarding, mobile cable yarder on trailer': {1928: 1.4027824821879459e-20, 1924: 3.4365045943961052e-37, 1925: 6.9939032596152882e-30, 1926: 1.0712940173393567e-25, 1927: 8.6539917152671678e-23},
                       'yarding and processing, mobile cable yarder on truck': {1928: 1.1679873528237404e-20, 1924: 2.8613089094435456e-37, 1925: 5.8232768671842113e-30, 1926: 8.9198283644271726e-26, 1927: 7.2055027953028907e-23},
                       'delimbing, with excavator-based processor': {1928: 1.6998969986716558e-20, 1924: 4.1643685881703105e-37, 1925: 8.4752370448040848e-30, 1926: 1.2981979323251926e-25, 1927: 1.0486938381883222e-22}})
    df2 = pd.Series({1928: 3.0638184091973243e-19, 1924: 7.5056562764093482e-36, 1925: 1.5275356821475311e-28, 1926: 2.3398091372066067e-24, 1927: 1.8901157781841223e-21})
    
    # Create pandas bar plot overlaid with line plot
    ax = df.sort_index().plot.bar(stacked=True, legend=False, figsize=(8,5))
    df2.sort_index().plot(use_index=False, ax=ax)
    
    # Optionally use a log scale with appropriate y-axis limits
    ax.set_yscale("log")
    ax.set_ylim((min(df2)/100));
    

    【讨论】:

      【解决方案3】:

      您可以使用ax.twiny()secondary_y=True,如下所示:

      import pandas as pd
      from matplotlib import pyplot as plt
      
      df = pd.DataFrame({'yarding, mobile cable yarder on trailer': {1928: 1.4027824821879459e-20, 1924: 3.4365045943961052e-37, 1925: 6.9939032596152882e-30, 1926: 1.0712940173393567e-25, 1927: 8.6539917152671678e-23},
                       'yarding and processing, mobile cable yarder on truck': {1928: 1.1679873528237404e-20, 1924: 2.8613089094435456e-37, 1925: 5.8232768671842113e-30, 1926: 8.9198283644271726e-26, 1927: 7.2055027953028907e-23},
                       'delimbing, with excavator-based processor': {1928: 1.6998969986716558e-20, 1924: 4.1643685881703105e-37, 1925: 8.4752370448040848e-30, 1926: 1.2981979323251926e-25, 1927: 1.0486938381883222e-22}})
      df2 = pd.Series({1928: 3.0638184091973243e-19, 1924: 7.5056562764093482e-36, 1925: 1.5275356821475311e-28, 1926: 2.3398091372066067e-24, 1927: 1.8901157781841223e-21})
      
      fig, ax = plt.subplots()
      ax2 = ax.twiny()
      df.plot(kind='bar', stacked=True, legend=False, ax=ax)
      df2.plot(kind='line', secondary_y=True)
      plt.show()    
      

      这会给你:

      您可能需要根据需要调整标签,例如:

      ax2.get_xaxis().set_visible(False)
      

      【讨论】:

        猜你喜欢
        • 2018-10-13
        • 2016-09-02
        • 2020-10-14
        • 1970-01-01
        • 2018-10-05
        • 1970-01-01
        • 1970-01-01
        • 2019-01-08
        • 1970-01-01
        相关资源
        最近更新 更多