【问题标题】:Edit the width of bars using dataframe.plot() function in matplotlib使用 matplotlib 中的 dataframe.plot() 函数编辑条的宽度
【发布时间】:2013-01-27 06:45:33
【问题描述】:

我正在使用以下方法制作堆积条形图:

DataFrame.plot(kind='bar',stacked=True)

我想控制条形的宽度,使条形像直方图一样相互连接。

我查看了文档但无济于事 - 有什么建议吗?这样可以吗?

【问题讨论】:

  • 想要传递 width=1 (到 bar)但情节不会让你...:s
  • 奇怪。 align 关键字的行为与 mpl 相反,而 log 关键字也很奇怪。 @Osmond,我会使用以下方法解决它: ax.bar(df.index.values, df.values)

标签: python matplotlib pandas histogram bar-chart


【解决方案1】:

对于遇到此问题的任何人:

从 pandas 0.14 开始,用条形图绘制有一个“宽度”命令: https://github.com/pydata/pandas/pull/6644

上面的例子现在可以简单地通过使用来解决

df.plot(kind='bar', stacked=True, width=1)

参见pandas.DataFrame.plot.barpandas.DataFrame.plotkind='bar'

在更改条形的宽度时,还可以通过指定figsize= 参数来更改图形大小。

【讨论】:

  • 虽然这是正确的答案,但也应该知道,增加宽度也会使条形重叠到相邻的刻度上。宽度的增加还应该伴随着将刻度位置按比例向右移动的代码。我很惊讶 matplotlib 的创建者默认没有对此进行编程。
【解决方案2】:

一个matplotlib解决方案

随意修改ax.bar中的width参数

代码

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

df = pd.DataFrame(np.arange(15).reshape(5, 3), columns=list('ABC'))

print(df)

fig, axs = plt.subplots(1, 2)

ax = axs[0]
xs = np.arange(df.shape[1])
ys = np.zeros(xs.shape)
for ind in df.index:
    ax.bar(xs, df.loc[ind, :], label=ind, bottom=ys, width=.4)
    ys += df.loc[ind, :]
plt.setp(ax, xticks=xs, xticklabels=list(df))
ax.legend(title='rows')
ax.set_xlabel('columns')

ax = axs[1]
xs = np.arange(df.shape[0])
ys = np.zeros(xs.shape)
for col in list(df):
    ax.bar(xs, df.loc[:, col], label=col, bottom=ys, width=.4)
    ys += df.loc[:, col]
plt.setp(ax, xticks=xs, xticklabels=df.index.to_numpy().tolist())
ax.legend(title='columns')
ax.set_xlabel('rows')

plt.show()

df=

    A   B   C
0   0   1   2
1   3   4   5
2   6   7   8
3   9  10  11
4  12  13  14

【讨论】:

    【解决方案3】:

    “我想控制条形的宽度,使条形像直方图一样相互连接。”

    更好的选择是使用 sns.displot()

    示例代码:

    emp = pd.read_csv("https://raw.githubusercontent.com/arora123/Data/master/emp-data.csv")
    
    sns.displot(emp, x='Department', hue='Gender', multiple='stack',  
                 height=8, aspect=1.7);
    

    【讨论】:

    • 请注意:代码将产生相同的情节但不一样的美学。我做了一些自定义以减少图表垃圾。
    【解决方案4】:

    如果您认为您必须使用 matplotlib 对条形图进行“后处理”,因为 pandas 在内部设置条形的宽度。

    构成条的矩形位于容器对象中。 所以你必须遍历这些容器并单独设置矩形的宽度:

    In [208]: df = pd.DataFrame(np.random.random((6, 5)) * 10,               
                            index=list('abcdef'), columns=list('ABCDE'))
    
    In [209]: df
    Out[209]: 
         A    B    C    D    E
    a  4.2  6.7  1.0  7.1  1.4
    b  1.3  9.5  5.1  7.3  5.6
    c  8.9  5.0  5.0  6.7  3.8
    d  5.5  0.5  2.4  8.4  6.4
    e  0.3  1.4  4.8  1.7  9.3
    f  3.3  0.2  6.9  8.0  6.1
    
    In [210]: ax = df.plot(kind='bar', stacked=True, align='center')
    
    In [211]: for container in ax.containers:
                  plt.setp(container, width=1)
       .....:         
    
    In [212]: x0, x1 = ax.get_xlim()
    
    In [213]: ax.set_xlim(x0 -0.5, x1 + 0.25)
    Out[213]: (-0.5, 6.5)
    
    In [214]: plt.tight_layout()
    

    【讨论】:

    • 不错的答案。我没有意识到“后处理”是一种选择
    • 我正在使用 df.plot 在现有条形图上过度绘制其他条形图。 @bmu,你的方法对我不起作用,因为它改变了所有旧的绘图对象,除了新的。如何仅更改 df.plot() 新创建的条的宽度?
    • @ChristopherBarrington-Leigh 也许您可以在以后的索引处(在您之前的容器对象的数量处)开始对容器对象的迭代,但是举个例子会更好。我认为你最好在一个单独的问题中提出这个问题。
    猜你喜欢
    • 2017-05-22
    • 2010-10-27
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多