I am trying to make a histogram and a density plot using the seaborn
module of Python
, and on the plot I am also trying to draw a vertical line at the mode. However, the resulting plot does not display any histogram and/or density curve. My code is below:
# a function to compute mode of the histograms shown in Figures `2` and `3` in the paper.
def compute_mode(layer_list):
ax = sns.distplot(layer_list, hist=False, kde=True, kde_kws={'linewidth': 2})
x = ax.lines[0].get_xdata()
y = ax.lines[0].get_ydata()
mode_idx = y.argmax()
mode_x = x[mode_idx]
plt.close()
return mode_x
# function to plot the histogram of the layer lists.
def make_density(layer_list, color):
# Plot formatting
plt.xlabel('Median Stn. MC-Loss')
plt.ylabel('Density')
# Draw the histogram and fit a density plot.
sns.distplot(layer_list, hist = True, kde = True,
kde_kws = {'linewidth': 2}, color=color)
# compute mode of the histogram.
mode_x = compute_mode(layer_list)
# draw a vertical line at the mode of the histogram.
plt.axvline(mode_x, color='blue', linestyle='dashed', linewidth=1.5)
plt.text(mode_x, 0.16, 'mode: {:.4f}'.format(mode_x))
layer_list = [ 1.0,2.0,3.0,4.0,2.0,3.0,1.0,6.0,10.0,2.0]
make_density(layer_list, 'green')
I think the problem arises from the line
plt.axvline(mode_x, color='blue', linestyle='dashed', linewidth=1.5)
and plt.text(mode_x, 0.16, 'mode: {:.4f}'.format(mode_x))
.
What am I doing wrong here?
Thank you,
The main problem is that in compute_mode()
plt.close()
is called, which closes the plot that was just before created in make_density()
. Note that sns.distplot
is mainly a drawing function which shouldn't be used just for calculations. As the kde was already plotted in make_density()
, ax.lines[0]
can be passed to compue_mode()
to extract the curve data without the need for creating the plot a second time.
Some other remarks:
distplot
has be deprecated, and is replaced by two functions: histplot
which creates a histogram, optionally with a kde. And displot
(without "T") which creates a grid of histogram/kdeplots. Apart from the name confusion, the kde_kws
parameter of distplot
is called line_kws
in histplot
, while kde_kws
in histplot
is meant for the function that calculates the KDE. Also, the kde curve always uses the same color as the histogram.ax
that can be used for additional formatting. In your original code you added some labels before calling distplot
, but as distplot
also might change settings, it is safer to do all these formatting calls afterwards.ax.set_xlabel()
and plt.xlabel()
.import matplotlib.pyplot as plt
import seaborn as sns
# a function to compute mode of the histograms shown in Figures `2` and `3` in the paper.
def compute_mode(line_object):
x = line_object.get_xdata()
y = line_object.get_ydata()
mode_idx = y.argmax()
return x[mode_idx], y[mode_idx]
# function to plot the histogram of the layer lists.
def make_density(layer_list, color):
# Draw the histogram and fit a density plot.
ax = sns.histplot(layer_list, kde=True,
line_kws={'linewidth': 2}, color=color)
# compute mode of the histogram.
mode_x, mode_y = compute_mode(ax.lines[0])
# draw a vertical line at the mode of the histogram.
ax.axvline(mode_x, color='blue', linestyle='dashed', linewidth=1.5)
ax.text(mode_x, mode_y, 'mode: {:.4f}'.format(mode_x))
# Plot formatting
ax.set_xlabel('Median Stn. MC-Loss')
ax.set_ylabel('Density')
layer_list = [1.0, 2.0, 3.0, 4.0, 2.0, 3.0, 1.0, 6.0, 10.0, 2.0]
make_density(layer_list, 'green')
plt.show()
Calling seaborn's distplot in compute_mode
without specifying the ax messed with the plot. You can simply replace compute_mode
by this code:
def compute_mode(layer_list):
dummy_fig, dummy_ax = plt.subplots()
ax = sns.distplot(layer_list, hist=False, kde=True, kde_kws={'linewidth': 2}, ax=dummy_ax)
x = ax.lines[0].get_xdata()
y = ax.lines[0].get_ydata()
mode_idx = y.argmax()
mode_x = x[mode_idx]
plt.close()
return mode_x
Even if this workaround works, consider to compute the mode with dedicated tools like scipy's gaussian_kde . It will prevent you from messing with graphical libraries to do math stuff.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.