15

I am using the following code, trying to plot the histogram of every column of a my pandas data frame df_in as subplot of a big figure.

%matplotlib notebook
from itertools import combinations
import matplotlib.pyplot as plt

fig, axes = plt.subplots(len(df_in.columns) // 3, 3, figsize=(12, 48))
for x in df_in.columns:
    df_in.hist(column = x, bins = 100)

fig.tight_layout()

However, the histogram didn't show in the subplot. Any one knows what I missed? Thanks!

4
  • 1
    AFAIK you need to specify ax parameter in df_in.hist(..., ax=your_ax) Commented Sep 22, 2016 at 18:14
  • BTW: from itertools import combinations is an unused import for this snippet Commented Jun 10, 2021 at 11:22
  • Is there a reason you want to define the subplots manually? Just writing df_in.hist(bins=100) should create the figure with subplots for each column. The for-loop is not needed. Commented Jan 9 at 14:38
  • This question is similar to: how to plot histograms from dataframes in pandas. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jan 9 at 14:39

4 Answers 4

14

I can't comment burhan's answer because I don't have enough reputation points. The problem with his answer is that axes isn't one-dimensional, it contains axes triads, so it needs to be unrolled:

%matplotlib notebook
from itertools import combinations
import matplotlib.pyplot as plt

fig, axes = plt.subplots(len(df_in.columns)//3, 3, figsize=(12, 48))

i = 0
for triaxis in axes:
    for axis in triaxis:
        df_in.hist(column = df_in.columns[i], bins = 100, ax=axis)
        i = i+1
Sign up to request clarification or add additional context in comments.

Comments

10
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

fig, axis = plt.subplots(2,3,figsize=(8, 8))
df_in.hist(ax=axis)

The above will plot a 2*3 (total 6 histogram for your dataframe). Adjust the rows and columns as per your arrangement requirements(# of columns)

My TA @Benjamin once told me , dataframe means do not have to use for loop.

Comments

3

You need to specify which axis you are plotting to. This should work:

fig, axes = plt.subplots(len(df_in.columns)//3, 3, figsize=(12, 48))
for col, axis in zip(df_in.columns, axes):
    df_in.hist(column = col, bins = 100, ax=axis)

3 Comments

I got this error: ValueError: The number of passed axes must be 1, the same as the output plot. How do I fix the axes here? Thanks
I didn't pay attention to the line that generate the axes. There may be a problem there, change it depending on how you want to present the plot. This will show all of them side by side for example. "fig, axes = plt.subplots(1, len(df_in.columns))". Let me know if this works.
I like this answer more than Pascal's below, but as he mentions there is an error. For me axes.flatten() did the trick
0

Stumbled on this ancient post and figured I'd add a correct answer, the above answers are mostly right but ignore the fact that they need to +1 the flooring function. Somewhat addressed in @burhan 's answer but just cleaned up a bit here:

import seaborn as sns
from matplotlib import pyplot as plt
import math

def plot_univariate_distributions(df, numcols=3, fig_kwargs = dict()):
    numrows = math.ceil(len(df.columns) / numcols)
    fig, axes = plt.subplots(numrows, numcols, **fig_kwargs)
    for col, ax in zip(df.columns, axes.flat):
        sns.histplot(df[col], ax=ax)
        ax.set_title(col, size=10)
    plt.tight_layout()

plot_univariate_distributions(mydf, fig_kwargs={'figsize':[10,5]})

2 Comments

Need to +1 before dividing by numcols likeplt.subplots( (1+len(df.columns)) // numcols, numcols, **fig_kwargs). This is to ensure the number of rows is calculated correctly when number of plots is divisible by numcols.
Thanks for catching! +1 wouldn't cover cases with more than 2 columns (e.g. 3 columns, 4 features, resolves to just 1 row (5 // 3 = 1). Added the math.ceil function to make it work and be a bit more intuitive

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.