Home > Software engineering >  Generate several subplots with a loop
Generate several subplots with a loop

Time:11-04

I want to show all average temperatures of each month in a small chart for every year. My first issue is printing the legend for the colder (blue) and warmer (respectively red) temperatures and giving colour to the chart itself. My second issue is connected with looping through the data, ending in getting the following error: TypeError: unsupported operand type(s) for /: 'tuple' and 'int'. The amount of the years doesn't always have to be an even number. How can I nicely represent that in the loop?

How can I nake the chart like the picture underneath, including the coloured legend and chart.

What I want:

  • displaying all the years with all average temperatures of each month
  • coloured legend and chart
  • (It doesn't matter whether matloblib or seaborn)
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
d = {'year': [2001, 2001, 2001, 2001, 
              2002, 2002, 2002, 2002],
     'month': [1, 2,3,4,
              1,2,3,4],
     'temperature': [10,20,15,20,
                     20,10,5,10]}
df = pd.DataFrame(data=d)

df.head()


fig, axs = plt.subplots(int(len(df.year.unique()) / 2), int(len(df.year.unique()) / 2))

for i in enumerate(df.year.unique()):
    for j in range(int(i/2)):
        for k in range(int(i/2)):
            month = df['month'].unique()
            temperature = df[df['year'] == i].groupby('month')['temperature'].mean().values
            axs[j][k].bar(month, temperature)
plt.show()
    


TypeError: unsupported operand type(s) for /: 'tuple' and 'int'

enter image description here

CodePudding user response:

Seaborn with its facetgrid integrated plots gets you quite far. Plotting years in rows and columns like this is as simple as just using col="year", col_wrap=10.

In seaborn we prefer to use the facetgrid enabled plotting functions since they are flexible, like shown here in this example with catplot.

Here's an example, with some random data to fill out

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

years = np.arange(1990, 2022, 1).reshape((-1, 1))
months = np.array([5, 6, 7, 8]).reshape((1, 4))
years, months = (np.broadcast_arrays(years, months))

d = {'year': years.flatten(),
     'month': months.flatten(),
     'temperature': np.random.randint(0, 25, size=years.size),
    }
df = pd.DataFrame(data=d)



fg = sns.catplot(data=df, kind='bar', x='month', y='temperature', hue='temperature',
                 palette='Reds', col='year', col_wrap=10,
                 height=2, aspect=0.8, dodge=False, ci=None);
fg.set_titles(col_template="{col_name}");
fg.legend.remove()

# Hackily add a colorbar too
norm = plt.Normalize(df.temperature.min(), df.temperature.max())
sm = plt.cm.ScalarMappable(cmap="Reds", norm=norm)
sm.set_array([])

cax = fg.figure.add_axes([0.96, .12, .02, .8])
fg.figure.colorbar(sm, cax=cax);

The fg is the facetgrid that we can use to access indidivual axes and do further tweaks. All axes would be accessed by using a loop over fg.axes.

The absolute weak point here is that seaborn doesn't support continuous hue coloring by values (It's a future project as of this writing, enter image description here

  • Related