Edit the width of bars using dataframe.plot() function in matplotlib
Question:
I am making a stacked bar plot using:
DataFrame.plot(kind='bar',stacked=True)
I want to control width of bars so that the bars are connected to each other like a histogram.
I’ve looked through the documentation but to no avail – any suggestions? Is it possible to do it this way?
Answers:
If think you have to “postprocess” the barplot with matplotlib as pandas internally sets the width of the bars.
The rectangles which form the bars are in container objects.
So you have to iterate through these containers and set the width of the rectangles individually:
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()
For anyone coming across this question:
Since pandas 0.14, plotting with bars has a ‘width’ command:
https://github.com/pydata/pandas/pull/6644
The example above can now be solved simply by using
df.plot(kind='bar', stacked=True, width=1)
See pandas.DataFrame.plot.bar
or pandas.DataFrame.plot
with kind='bar'
.
When changing the width of the bars, it might also be appropriate to change the figure size by specifying the figsize=
parameter.
"I want to control the width of bars so that the bars are connected to each other like a histogram."
A better option for the same is to use sns.displot()
Sample code:
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);
a matplotlib solution
modify the width
parameter in ax.bar
as you like
code
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
I am making a stacked bar plot using:
DataFrame.plot(kind='bar',stacked=True)
I want to control width of bars so that the bars are connected to each other like a histogram.
I’ve looked through the documentation but to no avail – any suggestions? Is it possible to do it this way?
If think you have to “postprocess” the barplot with matplotlib as pandas internally sets the width of the bars.
The rectangles which form the bars are in container objects.
So you have to iterate through these containers and set the width of the rectangles individually:
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()
For anyone coming across this question:
Since pandas 0.14, plotting with bars has a ‘width’ command:
https://github.com/pydata/pandas/pull/6644
The example above can now be solved simply by using
df.plot(kind='bar', stacked=True, width=1)
See pandas.DataFrame.plot.bar
or pandas.DataFrame.plot
with kind='bar'
.
When changing the width of the bars, it might also be appropriate to change the figure size by specifying the figsize=
parameter.
"I want to control the width of bars so that the bars are connected to each other like a histogram."
A better option for the same is to use sns.displot()
Sample code:
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);
a matplotlib solution
modify the width
parameter in ax.bar
as you like
code
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