Reputation: 41
I created a cumulative histogram. Now I want to draw a line from top of any bin to the y-axis in that histogram and show the value of it like this:
Can you show me the way to do? Below is my code to draw that histogram:
plt.rcParams['ytick.right'] = plt.rcParams['ytick.labelright'] = True
plt.rcParams['ytick.left'] = plt.rcParams['ytick.labelleft'] = False
plt.figure(figsize=[8, 6])
plt.hist(df['days'], bins=range(0, 50, 1), color="dodgerblue", edgecolor='black'
,cumulative=-1, density=True
,histtype='barstacked')
plt.xlabel('Number of Days')
plt.ylabel('Density')
Thank you so much!
Upvotes: 2
Views: 733
Reputation: 80319
Simply drawing a horizontal line rises two problems:
zorder=0
.plt.autoscale(enable=True, axis='x', tight=True)
solves that.To add a new tick at the specific y-position, you can take the list of existing ticks, create a list including the new tick and set those as the new ticks.
To change the color of the newly added tick, you first find its index in the list, and then change the color of the tick with that index.
One problem with this approach, is that the new tick might overlap with an existing tick. This could be solved by looping through the list and if an existing tick is nearer than some epsilon to the new tick, remove the existing tick. This is not yet implemented in the code example.
Alternatively, the tick value could be displayed to the left of the axis, on top of the horizontal line. Of course, that would lead to a problem in case there wouldn't be enough place for the text.
You might want to round the value of the special tick to the nearest hundredths to prevent that the other ticks also get displayed with more digits.
I created an example with simulated data:
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
df = pd.DataFrame({"days": np.random.normal(25, 10, 10000)})
plt.rcParams['ytick.right'] = plt.rcParams['ytick.labelright'] = True
plt.rcParams['ytick.left'] = plt.rcParams['ytick.labelleft'] = False
plt.figure(figsize=[8, 6])
bin_heights, _, _ = plt.hist(df['days'], bins=range(0, 50, 1), color="dodgerblue", edgecolor='black',
cumulative=-1, density=True,
histtype='barstacked')
plt.autoscale(enable=True, axis='both', tight=True) # use axis='x' to only set the x axis tight
special_y = bin_heights[15]
# draw a horizontal line, use zorder=0 so it is drawn behind the bars
plt.axhline(special_y, 0, 1, color='red', linestyle='dashed', linewidth=1, zorder=0)
plt.yticks(list(plt.yticks()[0]) + [special_y]) # add a tick in y for special_y
# find the index of special_y in the new ticks (ticks are sorted automatically)
index_special_y = list(plt.yticks()[0]).index(special_y)
plt.gca().get_yticklabels()[index_special_y].set_color('red') # change the color of the special tick
plt.xlabel('Number of Days')
plt.ylabel('Density')
plt.show()
Upvotes: 0
Reputation: 1540
Oneliner:
plt.axhline(y, color='k', linestyle='dashed', linewidth=1)
Use this to add a horizontal line to your histogram.
Place your mean or value of y in place of y in the above code snippet.
Upvotes: 2