Reputation: 287
I have a data named prices
, and I use a prices.tail(1)
to build a histogram.
Also I have some variables: left_border = 341.086
, right_border = 437.177
, line_length = 1099
.
And the next code:
plt.figure(figsize=(9,6))
plt.hist(prices.tail(1), bins = 400)
x2 = [left_border,left_border]
y2 = [0, line_length]
plt.plot(x2, y2, color = 'green')
x3 = [right_border, right_border]
y3 = [0, line_length]
plt.plot(x3, y3, color = 'green')
plt.show()
Produce an output:
How I can colour part of histogram which is between the green borders differently from part outside the green borders, gradientally? Also to pick bins which are nearly by green borders and turn them into another colour?
Thanks.
Upvotes: 0
Views: 1830
Reputation: 80449
The exact meaning of 'gradiently' here is uncertain to me. Here are some ideas that can serve as a base to create the desired solution.
hist
returns the values of each bin, the limits of the bins and the patches that were drawn; you can color the patches depending on their mean x-position sqrt
can be used to make the effect start quickeraxvspan
can draw a vertical span between two given x coordinates; set zorder=0
to make sure the span stays behind the histogram bars; or set an alpha=0.3
to draw it as a transparent layer over the barsimport matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import numpy as np
prices_np = 14*np.random.normal(5, 1, 10000)**2
left_border = 341.086
right_border = 437.177
# line_length = 1099
divisor_tickness = 10
main_color = mcolors.to_rgb('dodgerblue')
highlight_color = mcolors.to_rgb('limegreen')
divisor_color = mcolors.to_rgb('crimson')
binvals, bins, patches = plt.hist(prices_np, bins = 400, color=main_color)
bin_centers = 0.5 * (bins[:-1] + bins[1:])
for p, x in zip(patches, bin_centers):
#x, _ = p.get_xy()
#w = p.get_width()
if left_border < x < right_border:
f = 2*min(x-left_border, right_border-x) / (right_border - left_border)
f = f ** 0.5
p.set_facecolor([ (h_rgb*f + m_rgb * (1-f)) for m_rgb, h_rgb in zip(main_color, highlight_color)] )
elif left_border-divisor_tickness < x <= left_border or right_border <= x < right_border + divisor_tickness:
p.set_facecolor(divisor_color)
plt.axvspan(left_border, right_border, color='lightgoldenrodyellow', zorder=0)
plt.show()
To get a smooth gradient depending on the bar heights, a gaussian kde could be useful:
kde = gaussian_kde(prices_np)
max_kde = max([kde(x)[0] for x in bin_centers])
for x, p in zip(bin_centers, patches):
p.set_facecolor(plt.cm.viridis((kde(x)[0] / max_kde) ))
Upvotes: 4