How to arrange 4 Seaborn plots in a grid (Python)? - python

I would like to arrange four Seaborn plots in a 2 x 2 grid. I tried the following code but I got an exception. I would also like to know how to set titles and xlabel, ylabel in the subplots and a title for the overall grid plot.
Some toy data:
df
'{"age":{"76":33,"190":30,"255":36,"296":27,"222":19,"147":39,"127":23,"98":24,"168":29,"177":39,"197":27,"131":36,"36":30,"219":28,"108":38,"198":34,"40":32,"246":24,"109":26,"117":47,"20":26,"113":24,"279":35,"120":35,"7":26,"119":28,"272":24,"66":28,"87":28,"133":28},"Less_than_College":{"76":1,"190":1,"255":0,"296":1,"222":1,"147":1,"127":0,"98":0,"168":1,"177":1,"197":0,"131":1,"36":0,"219":0,"108":0,"198":0,"40":0,"246":0,"109":1,"117":1,"20":0,"113":0,"279":0,"120":0,"7":0,"119":1,"272":0,"66":1,"87":0,"133":0},"college":{"76":0,"190":0,"255":0,"296":0,"222":0,"147":0,"127":1,"98":1,"168":0,"177":0,"197":1,"131":0,"36":1,"219":1,"108":0,"198":1,"40":1,"246":0,"109":0,"117":0,"20":1,"113":1,"279":0,"120":1,"7":1,"119":0,"272":0,"66":0,"87":1,"133":1},"Bachelor":{"76":0,"190":0,"255":1,"296":0,"222":0,"147":0,"127":0,"98":0,"168":0,"177":0,"197":0,"131":0,"36":0,"219":0,"108":1,"198":0,"40":0,"246":1,"109":0,"117":0,"20":0,"113":0,"279":1,"120":0,"7":0,"119":0,"272":1,"66":0,"87":0,"133":0},"terms":{"76":30,"190":15,"255":30,"296":30,"222":30,"147":15,"127":15,"98":15,"168":30,"177":30,"197":15,"131":30,"36":15,"219":15,"108":30,"198":7,"40":30,"246":15,"109":15,"117":15,"20":15,"113":15,"279":15,"120":15,"7":15,"119":30,"272":15,"66":30,"87":30,"133":15},"Principal":{"76":1000,"190":1000,"255":1000,"296":1000,"222":1000,"147":800,"127":800,"98":800,"168":1000,"177":1000,"197":1000,"131":1000,"36":1000,"219":800,"108":1000,"198":1000,"40":1000,"246":1000,"109":1000,"117":1000,"20":1000,"113":800,"279":800,"120":800,"7":800,"119":1000,"272":1000,"66":1000,"87":1000,"133":1000}}'
fig = plt.figure()
fig.subplots_adjust(hspace=0.4, wspace=0.4)
ax = fig.add_subplot(2, 2, 1)
ax.sns.distplot(df.Principal)
ax = fig.add_subplot(2, 2, 2)
ax.sns.distplot(df.terms)
ax = fig.add_subplot(2, 2, 3)
ax.sns.barplot(data = df[['Less_than_College', 'college', 'Bachelor', ]])
ax = fig.add_subplot(2, 2, 4)
ax.sns.boxplot(data = df['age'])
plt.show()
AttributeError: 'AxesSubplot' object has no attribute 'sns'

ax is matplotlib object that do not have sns attribute, because of this you are getting error. sns is seaborn object. If you want to use ax object with seaborn plot for your case pass parameter ax=ax in seaborn object as follows:
fig = plt.figure()
fig.subplots_adjust(hspace=0.4, wspace=0.4)
ax = fig.add_subplot(2, 2, 1)
sns.distplot(df.Principal,ax=ax)
ax = fig.add_subplot(2, 2, 2)
sns.distplot(df.terms,ax=ax)
ax = fig.add_subplot(2, 2, 3)
sns.barplot(data = df[['Less_than_College', 'college', 'Bachelor']],ax=ax)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
ax = fig.add_subplot(2, 2, 4)
sns.boxplot(df['age'],ax=ax)
plt.show()
The plot looks like this.

Related

How to Remove duplicate labels in subplot legend

The following code will generate a legend with duplicated labels. How to remove the duplicated one, so that there is only 1 label1 and 1 label2? One possible approach is to remove the duplicated item in the lines_labels list, but I couldn't figure out the code. Can someone please help? Thanks a lot!
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.scatter(1,2,label='a',color='black')
ax1.plot(np.array([1, 2]), np.array([1, 2]),color='b',label='xvalues')
ax2.scatter(3,4,label='a',color='black')
ax3.scatter(5,6,label='b',color='red')
ax4.scatter(7,8,label='b',color='red')
lines_labels = [ax.get_legend_handles_labels() for ax in fig.axes]
lines, labels = [sum(lol, []) for lol in zip(*lines_labels)]
fig.legend(lines, labels, scatterpoints = 1)
plt.show()
you could put all labels and lines in a dict and filter only for unique labels like this
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(223)
ax4 = fig.add_subplot(224)
ax1.scatter(1, 2, label='a', color='black')
ax1.plot(np.array([1, 2]), np.array([1, 2]), color='b', label='xvalues')
ax2.scatter(3, 4, label='a', color='black')
ax3.scatter(5, 6, label='b', color='red')
ax4.scatter(7, 8, label='b', color='red')
lines_labels = [ax.get_legend_handles_labels() for ax in fig.axes]
lines, labels = [sum(lol, []) for lol in zip(*lines_labels)]
# grab unique labels
unique_labels = set(labels)
# assign labels and legends in dict
legend_dict = dict(zip(labels, lines))
# query dict based on unique labels
unique_lines = [legend_dict[x] for x in unique_labels]
fig.legend(unique_lines, unique_labels, scatterpoints=1)
plt.show()

Get pandas boxplot in one plot and matplotlib plot in another figure

import pandas as pd
import matplotlib.pyplot as plt
def csv_til_liste(filnavn):
occuDF = pd.read_csv(filnavn)
occuList=occuDF.values.tolist()
return occuDF, occuList
occuDF, occuList = csv_til_liste("occupancy.csv")
plt.figure(1)
occuDF.boxplot(column = 'Temperature', by = 'Occupancy')
plt.suptitle('')
x=(1, 2, 3, 4, 5)
y=(1,2,3,4,5)
plt.figure(2)
plt.plot(x,y)
plt.show()
When I run the program, the two plots are plotted in one figure, but I want them in two separate figures.
The pandas.DataFrame.boxplot takes an ax parameter, as written in the docs.
So you can use:
fig1 = plt.figure()
ax1 = fig1.add_subplot(1, 1, 1)
occuDF.boxplot(column = 'Temperature', by = 'Occupancy', ax=ax1)
plt.suptitle('')
x=(1, 2, 3, 4, 5)
y=(1,2,3,4,5)
fig2 = plt.figure(2)
ax2 = fig2.add_subplot(1, 1, 1)
ax2.plot(x,y)
plt.show()
Otherwise, you can plot in different subplots of the same figure by applying minimal changes.

setting axis labels in axes from matplotlib

I'm trying the following code to plot some graphs:
fig = plt.figure(figsize=(10, 20))
for idx, col in enumerate(['Pclass', 'Sex']):
ax = fig.add_subplot(2, 1, idx+1)
_ = ax.set(ylabel='Counts')
_ = sns.countplot(x=col, hue='Survived', data=full, ax=ax)
The output I'm getting is:
As you can see the y label is set as the seaborn countplot default label 'count', but I want to change it to 'Counts'. I've tried the axes method set_ylabel and set with ylabel argument and got no changes in the graphs. What am I doing wrong?
Can you try the following, changing the ylabel after plotting
fig = plt.figure(figsize=(10, 20))
for idx, col in enumerate(['Pclass', 'Sex']):
ax = fig.add_subplot(2, 1, idx+1)
sns.countplot(x=col, hue='Survived', data=full, ax=ax)
ax.set_ylabel('Counts')

Variable wspace with gridspec.GridSpec in python

I would like to make a variable (two different) wspace using GridSpec in matplotlib.
I would like to achieve the following:
I'm using the following so far:
gs1 = gridspec.GridSpec(6, 3, width_ratios=[1.5,1,1])
gs1.update(wspace=0.4, hspace=0.3)
ax1 = fig.add_subplot(gs1[0:2,0])
ax2 = fig.add_subplot(gs1[2:4,0])
ax3 = fig.add_subplot(gs1[4:6,0])
ax4 = fig.add_subplot(gs1[0:3,1])
ax5 = fig.add_subplot(gs1[3:6,1])
ax6 = fig.add_subplot(gs1[0:3,2])
ax7 = fig.add_subplot(gs1[3:6,2])
Any idea how to obtain the two different space highlighted in green in my amazing hand drawing ?
Thanks a lot !
Sam
You may use 2 GridSpecs, one which contains one column and 3 rows and one which contains two rows and two colums. You can then let the first extend only to less than half of the figure and start the second at half the figure width. The difference between the left and right parameter will be the spacing.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
fig = plt.figure()
gs1 = GridSpec(3, 1, right=0.4)
gs2 = GridSpec(2, 2, left=0.5)
ax1 = fig.add_subplot(gs1[0,0])
ax2 = fig.add_subplot(gs1[1,0])
ax3 = fig.add_subplot(gs1[2,0])
ax4 = fig.add_subplot(gs2[0,0])
ax5 = fig.add_subplot(gs2[0,1])
ax6 = fig.add_subplot(gs2[1,0])
ax7 = fig.add_subplot(gs2[1,1])
plt.show()
The same can be achieved with first defining an "outer" gridspec with two columns and placing an inner gridspec into each of them.
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec
fig = plt.figure()
gs = GridSpec(1, 2, width_ratios=[1.5,2], wspace=0.3)
gs1 = GridSpecFromSubplotSpec(3, 1, subplot_spec=gs[0])
gs2 = GridSpecFromSubplotSpec(2, 2, subplot_spec=gs[1])
ax1 = fig.add_subplot(gs1[0,0])
ax2 = fig.add_subplot(gs1[1,0])
ax3 = fig.add_subplot(gs1[2,0])
ax4 = fig.add_subplot(gs2[0,0])
ax5 = fig.add_subplot(gs2[0,1])
ax6 = fig.add_subplot(gs2[1,0])
ax7 = fig.add_subplot(gs2[1,1])
plt.show()

Display two bar charts one by one in MATPLOTLIB

I am plotting bar charts using pivot tables. I have two independent pivot tables and need to produce two bar charts side-by-side and save it as a PNG image. Using this code, the chart is generated but it won't display as expected.
What I tried:
# Plotting Activity Begins
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(2, 2, 1)
vig = task_frame.plot(kind="bar", figsize=(8, 6), stacked=True, width=0.3, rot=20)
print "ax1",ax1
print "vig",vig
vicky = issue_frame.plot(kind="bar", figsize=(8, 6), stacked=True, width=0.3, rot=90)
print "ax2",ax2
print "vicky",vicky
plt.ylim((0, 10))
plt.rcParams.update({'font.size': 10})
plt.savefig("/tmp/" + str(current_date) + ".png")
My print statement values:
ax1 Axes(0.125,0.1;0.352273x0.8)
vig Axes(0.125,0.1;0.775x0.8)
ax2 Axes(0.125,0.536364;0.352273x0.363636)
vicky Axes(0.125,0.1;0.775x0.8)
How can I display the charts as side-by-side pictures in a single image? Where should I assign the ax1 and ax2 value?
When you plot try to add axes instance to plot function, like here:
...
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(2, 2, 1)
task_frame.plot(..., ax=ax1)
issue_frame.plot(..., ax=ax2)
...

Categories

Resources