【问题标题】:How to create bar chart with secondary_y from dataframe如何从数据框中使用secondary_y创建条形图
【发布时间】:2013-05-13 14:35:25
【问题描述】:

我想创建一个包含在 Pandas 数据框中的两个系列(比如“A”和“B”)的条形图。如果我只想使用不同的 y 轴来绘制它们,我可以使用 secondary_y:

df = pd.DataFrame(np.random.uniform(size=10).reshape(5,2),columns=['A','B'])
df['A'] = df['A'] * 100
df.plot(secondary_y=['A'])

但如果我想创建条形图,则忽略等效命令 (它不会在 y 轴上放置不同的刻度),因此“A”中的条形太大以至于无法区分“B”中的条:

df.plot(kind='bar',secondary_y=['A'])

如何直接在 pandas 中执行此操作?或者您将如何创建这样的图表?

我使用的是 pandas 0.10.1 和 matplotlib 1.2.1 版。

【问题讨论】:

  • 等效命令不起作用是什么意思?是没有图,还是图不符合你的预期?
  • 请发布错误或描述什么不工作
  • 您尝试过手动实现什么?你看过gallery吗?
  • 不,一切顺利。你有同样大小的酒吧吗?您使用的是哪个版本?
  • 明白,抱歉,我完全错过了那条关键线(现在回想起来很明显)。这在 pandas 0.11 中也不起作用,我建议在 github 上将其提交为 issue

标签: python matplotlib pandas


【解决方案1】:

不要认为 pandas 图形支持这一点。做了一些手动matplotlib代码..你可以进一步调整它

import pylab as pl
fig = pl.figure()
ax1 = pl.subplot(111,ylabel='A')
#ax2 = gcf().add_axes(ax1.get_position(), sharex=ax1, frameon=False, ylabel='axes2')
ax2 =ax1.twinx()
ax2.set_ylabel('B')
ax1.bar(df.index,df.A.values, width =0.4, color ='g', align = 'center')
ax2.bar(df.index,df.B.values, width = 0.4, color='r', align = 'edge')
ax1.legend(['A'], loc = 'upper left')
ax2.legend(['B'], loc = 'upper right')
fig.show()

我确信有办法强制单条进一步调整它。将条形移得更远,一个稍微透明等。

【讨论】:

    【解决方案2】:

    好的,我最近遇到了同样的问题,即使这是一个老问题,我认为我可以为这个问题提供一个答案,以防其他人对此失去理智。 Joop 给出了要做的事情的基础,当您的数据框中只有(例如)两列时,这很容易,但是当您的两个轴有不同数量的列时,它变得非常讨厌,因为您需要使用 pandas plot() 函数的 position 参数。在我的示例中,我使用 seaborn,但它是可选的:

    import pandas as pd
    import seaborn as sns
    import pylab as plt
    import numpy as np
    
    df1 = pd.DataFrame(np.array([[i*99 for i in range(11)]]).transpose(), columns = ["100"], index = [i for i in range(11)])
    df2 = pd.DataFrame(np.array([[i for i in range(11)], [i*2 for i in range(11)]]).transpose(), columns = ["1", "2"], index = [i for i in range(11)])
    
    fig, ax = plt.subplots()
    ax2 = ax.twinx()
    
    # we must define the length of each column. 
    df1_len = len(df1.columns.values)
    df2_len = len(df2.columns.values)
    column_width = 0.8 / (df1_len + df2_len)
    
    # we calculate the position of each column in the plot. This value is based on the position definition :
    # Specify relative alignments for bar plot layout. From 0 (left/bottom-end) to 1 (right/top-end). Default is 0.5 (center)
    # http://pandas.pydata.org/pandas-docs/dev/generated/pandas.DataFrame.plot.html
    df1_posi = 0.5 + (df2_len/float(df1_len)) * 0.5
    df2_posi = 0.5 - (df1_len/float(df2_len)) * 0.5
    
    # In order to have nice color, I use the default color palette of seaborn
    df1.plot(kind='bar', ax=ax, width=column_width*df1_len, color=sns.color_palette()[:df1_len], position=df1_posi)
    df2.plot(kind='bar', ax=ax2, width=column_width*df2_len, color=sns.color_palette()[df1_len:df1_len+df2_len], position=df2_posi)
    
    ax.legend(loc="upper left")
    
    # Pandas add line at x = 0 for each dataframe.
    ax.lines[0].set_visible(False)
    ax2.lines[0].set_visible(False)
    
    # Specific to seaborn, we have to remove the background line 
    ax2.grid(b=False, axis='both')
    
    # We need to add some space, the xlim don't manage the new positions
    column_length = (ax2.get_xlim()[1] - abs(ax2.get_xlim()[0])) / float(len(df1.index))
    ax2.set_xlim([ax2.get_xlim()[0] - column_length, ax2.get_xlim()[1] + column_length])
    
    fig.patch.set_facecolor('white')
    plt.show()
    

    结果:http://i.stack.imgur.com/LZjK8.png

    我没有测试所有可能性,但无论您使用的每个数据框中的列数如何,它看起来都可以正常工作。

    【讨论】:

      猜你喜欢
      • 2021-12-23
      • 1970-01-01
      • 2018-12-22
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多