MatPlotLib Python 3.4: Enumerate and ax.annotate - python

I have constructed a horizontal bar chart as show with the code below.
Everything looks great except what are supposed to be annotated bars.
I can't figure out how to get the labels on the end of the bars and not in a table in the middle of the chart. Specifically, I'm looking at these lines of code:
for i, text in enumerate(ind):
ax.annotate(str(x_axis), (ind[i], x_axis[i]),fontsize=14, color='black', va='center', ha='center')
Here's the whole thing:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
%matplotlib inline
df0=pd.read_csv('sample1.csv')
fig, ax = plt.subplots(1, 1, figsize=(12,9))
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
x_axis = 8.6667, 9.5, -8.4, 0, -4, 6
y_axis = Hospital
y_axis = 'A','B','C','D','E','F'
ind = np.arange(len(y_axis))
plt.xticks(fontsize=12)
plt.yticks(ind, y_axis, fontsize=14)
plt.tick_params(
axis='x',
which='both',
top='off')
plt.tick_params(
axis='y',
which='both',
right='off',
left='off')
plt.title('Super Awesome Title', fontsize=18, ha='center')
#Label Bars: First is the older, simpler way but it has issues...
#for a, b in zip(ind, y_axis):
# plt.text(a, b, str(b), fontsize=16, color='black')
#Better, but more complex method:
for i, text in enumerate(ind):
ax.annotate(str(x_axis), (ind[i], x_axis[i]),fontsize=14, color='black', va='center', ha='center')
#Add padding around x_axis
plt.xlim([min(x_axis)-.5, max(x_axis)+.5])
#Add padding around y_axis
plt.ylim([min(ind)-.5, max(ind)+.5])
plt.barh(ind, x_axis, align='center', height=0.5, edgecolor='none', color='#AAA38E')

I just figured it out:
I had to switch ind and x_axis around and iterate over the x_axis:
ax.annotate(str(x_axis), (ind[i], x_axis[i])
should be:
ax.annotate(str(x_axis[i]), (x_axis[i], ind[i])

Related

multiple axis not starting at zero

I Darw a graph with mutliple axix, have several questios:
why the left y-axsis is not satrting from zero. (I mean the zero point
is not at the begining of the y-axix).
I only want major grid for the x-axis (a major grid line for each week) but the code add a mjor
grid for the y-axix also.
How can i add minor grid for y-axix (the red one (ax2))
i want to change the color for the x-axis labels (Dates) color to black
import matplotlib.pyplot as plt
Hits= pd.read_excel("stackoverflow_example.xlsx", sheet_name="data")
fig=plt.figure(figsize=(20,10))
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax.bar(Hits['Date'], Hits['Total'], width=0.35, color="b" )
ax.set_ylabel('Hits', color="b",size=16)
ax.yaxis.set_label_position('right')
ax.tick_params(axis='y', colors="b")
ax.tick_params(axis='x', colors="b", rotation=45)
ax.yaxis.tick_right()
ax2.plot(Hits['weeks'], Hits['Cases'], linewidth= 3.5, color="Red")
ax2.set_ylabel("Cases", color="Red",size=16)
ax2.tick_params(axis='y', colors="Red", size=16)
ax2.xaxis.set_ticks_position('top')
major_ticks = np.arange(0, 10, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', alpha=0.5)
plt.show()
My data
[
Graph:
If you want to start from zero, you can do that with 'ax2.set_ylim()'. After that, you can specify the axes for the grid. If the color is black, you can set color='k'.
import matplotlib.pyplot as plt
fig=plt.figure(figsize=(20,10))
ax=fig.add_subplot(111, label="1")
ax2=fig.add_subplot(111, label="2", frame_on=False)
ax.bar(Hits['Date'], Hits['Total'], width=0.35, color="b" )
ax.set_ylabel('Hits', color="b",size=16)
ax.yaxis.set_label_position('right')
ax.tick_params(axis='y', colors="b")
ax.tick_params(axis='x', colors="k", rotation=45)
ax.yaxis.tick_right()
ax2.plot(Hits['weeks'], Hits['Cases'], linewidth= 3.5, color="Red")
ax2.set_ylabel("Cases", color="Red",size=16)
ax2.tick_params(axis='y', colors="Red", size=16)
ax2.xaxis.set_ticks_position('top')
ax2.set_ylim(0,62) # update
major_ticks = np.arange(0, 10, 1)
ax.set_xticks(major_ticks)
ax.grid(which='major', axis='x', alpha=0.5) #update
ax2.grid(which='major', axis='y', alpha=0.5) # update
plt.show()

How to make a bar chart with only a height indicator not showing the full bar?

This chart almost looks good but is probably not the way to model this in matplotlib. How to have two horizontal bars that extend to the left and right of vertical line at an x-point to show the change of the two datasets eg SDR from 0.7 to 0.25.
Currently i patch things together with '$-$' markers which make misaligned legends and i am not able to place properly. If i change the figsize the markers start misaligning from the vertical bar at their x-point, eg SDR.
How to model this kind of chart proberly?
layer0 = np.random.random(10)
fig, ax = plt.subplots(1,1, figsize=(15/2,1.5*2.5),)
ind = np.arange(10, dtype=np.float64)*1#cordx
ax.plot(ind[0::2]+0.05, layer0[0::2]-0.04, ls='None', marker='$-$', markersize=40)
ax.plot(ind[1::2]-0.15, layer0[1::2]-0.04, ls='None', marker='$-$', markersize=40)
ax.set_ylim(0,1.05)
ax.set_yticks(np.arange(0, 1.1, step=0.1))
ax.set_xticks(ind[0::2]+0.5)
ax.set_xticklabels( ('SDR', 'SSR', 'SCR', 'RCR', 'GUR') )
plt.grid(b=True)
plt.grid(color='black', which='major', axis='y', linestyle='--', lw=0.2)
plt.show()
Alternatively, you can use a horizontal bar chart barh which is more intuitive in this case. Here the key parameter is left which will shift your horizontal bar charts to left/right.
Following is a complete answer:
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2)
layer0 = np.random.random(10)
fig, ax = plt.subplots(1,1, figsize=(15/2,1.5*2.5),)
n = 10
width = 0.5
ind = np.arange(n, dtype=np.float64)*1#cordx
ax.barh(layer0[0::2], [width]*int(n/2), height=0.01, left = ind[0::2])
ax.barh(layer0[1::2], [width]*int(n/2), height=0.01, left = ind[0::2]+width)
ax.set_ylim(0,1.05)
ax.set_yticks(np.arange(0, 1.1, step=0.1))
ax.set_xticks(ind[0::2]+0.5)
ax.set_xticklabels( ('SDR', 'SSR', 'SCR', 'RCR', 'GUR') )
plt.grid(b=True)
plt.grid(color='black', which='major', axis='y', linestyle='--', lw=0.2)
plt.show()
up until now i havent thought of bar charts with bottom offset, which seems to be ok:
layer0 = np.random.random(10)
fig, ax = plt.subplots(1,1, figsize=(15/1.3,1.5*2.5),)# sharey=True)
ind = np.arange(10, dtype=np.float64)*1#cordx
height=0.03
width=0.8
ax.bar(ind[0::2]-width/2, height, width=width, bottom=layer0[0::2]-height)
ax.bar(ind[0::2]+width/2, height, width=width, bottom=layer0[1::2]-height)
ax.set_ylim(-0.,1.05)
plt.grid(color='black', which='major', axis='x', linestyle='-', lw=0.8)

Hide the short lines of axis tickers in plt.subplots [duplicate]

I can remove the ticks with
ax.set_xticks([])
ax.set_yticks([])
but this removes the labels as well. Any way I can plot the tick labels but not the ticks and the spine
You can set the tick length to 0 using tick_params (http://matplotlib.org/api/axes_api.html#matplotlib.axes.Axes.tick_params):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([1],[1])
ax.tick_params(axis=u'both', which=u'both',length=0)
plt.show()
Thanks for your answers #julien-spronck and #cmidi.
As a note, I had to use both methods to make it work:
import numpy as np
import matplotlib.pyplot as plt
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(11, 3))
data = np.random.random((4, 4))
ax1.imshow(data)
ax1.set(title='Bad', ylabel='$A_y$')
# plt.setp(ax1.get_xticklabels(), visible=False)
# plt.setp(ax1.get_yticklabels(), visible=False)
ax1.tick_params(axis='both', which='both', length=0)
ax2.imshow(data)
ax2.set(title='Somewhat OK', ylabel='$B_y$')
plt.setp(ax2.get_xticklabels(), visible=False)
plt.setp(ax2.get_yticklabels(), visible=False)
# ax2.tick_params(axis='both', which='both', length=0)
ax3.imshow(data)
ax3.set(title='Nice', ylabel='$C_y$')
plt.setp(ax3.get_xticklabels(), visible=False)
plt.setp(ax3.get_yticklabels(), visible=False)
ax3.tick_params(axis='both', which='both', length=0)
plt.show()
While attending a coursera course on Python, this was a question.
Below is the given solution, which I think is more readable and intuitive.
ax.tick_params(top=False,
bottom=False,
left=False,
right=False,
labelleft=True,
labelbottom=True)
This worked for me:
plt.tick_params(axis='both', labelsize=0, length = 0)
matplotlib.pyplot.setp(*args, **kwargs) is used to set properties of an artist object. You can use this in addition to get_xticklabels() to make it invisible.
something on the lines of the following
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(2,1,1)
ax.set_xlabel("X-Label",fontsize=10,color='red')
plt.setp(ax.get_xticklabels(),visible=False)
Below is the reference page
http://matplotlib.org/api/pyplot_api.html
You can set the yaxis and xaxis set_ticks_position properties so they just show on the left and bottom sides, respectively.
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
Furthermore, you can hide the spines as well by setting the set_visible property of the specific spine to False.
axes[i].spines['right'].set_visible(False)
axes[i].spines['top'].set_visible(False)
This Worked out pretty well for me! try it out
import matplotlib.pyplot as plt
import numpy as np
plt.figure()
languages =['Python', 'SQL', 'Java', 'C++', 'JavaScript']
pos = np.arange(len(languages))
popularity = [56, 39, 34, 34, 29]
plt.bar(pos, popularity, align='center')
plt.xticks(pos, languages)
plt.ylabel('% Popularity')
plt.title('Top 5 Languages for Math & Data \nby % popularity on Stack Overflow',
alpha=0.8)
# remove all the ticks (both axes),
plt.tick_params(top='off', bottom='off', left='off', right='off', labelleft='off',
labelbottom='on')
plt.show()
Currently came across the same issue, solved as follows on version 3.3.3:
# My matplotlib ver: 3.3.3
ax.tick_params(tick1On=False) # "for left and bottom ticks"
ax.tick_params(tick2On=False) # "for right and top ticks, which are off by default"
Example:
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
ax.tick_params(tick1On=False)
plt.show()
Output:
Assuming that you want to remove some ticks on the Y axes and only show the yticks that correspond to the ticks that have values higher than 0 you can do the following:
from import matplotlib.pyplot as plt
fig, ax = plt.subplots()
# yticks and yticks labels
yTicks = list(range(26))
yTicks = [yTick if yTick % 5 == 0 else 0 for yTick in yTicks]
yTickLabels = [str(yTick) if yTick % 5 == 0 else '' for yTick in yTicks]
Then you set up your axis object's Y axes as follow:
ax.yaxis.grid(True)
ax.set_yticks(yTicks)
ax.set_yticklabels(yTickLabels, fontsize=6)
fig.savefig('temp.png')
plt.close()
And you'll get a plot like this:

Matplotlib Horizontal Bars: Value Error

For some reason, whenever I run the code below I get a Value Error: Could not convert string to float: 'A'
I change a comma to a decimal point below so the lengths line up between axes.
import numpy as np
import matplotlib.pyplot as plt
plt.rcdefaults()
%matplotlib inline
fig, ax = plt.subplots(1, 1, figsize=(12,9))
ax.spines['top'].set_visible(False)
ax.spines['bottom'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.spines['left'].set_visible(False)
x_axis = 8.6667, 9.5, -8.4, 0, -4, 6
y_axis = 'A','B','C','D','E','F'
ind = np.arange(len(y_axis))
plt.xticks(fontsize=12)
plt.yticks(ind, y_axis, fontsize=14)
plt.tick_params(
axis='x',
which='both',
top='off')
plt.tick_params(
axis='y',
which='both',
right='off',
left='off')
plt.title('Super Awesome Title', fontsize=18, ha='center')
for a, b in zip(y_axis, ind):
plt.text(a, b, str(a), fontsize=16, color='black')
plt.barh(ind, x_axis)

Python: Suplots with secondary-axis

I wrote the following code below to do the following graph:
fig, ax = plt.subplots(figsize=(8, 6))
ax.patch.set_facecolor('white')
ax.plot(df.index, df.X1.values, 'b',
label='NMA', linewidth=1.5)
ax.set_ylabel('Index')
ax2 = ax.twinx()
ax2.plot(df.index, df.Y.values, 'r--',
label='Rate', linewidth=1.5)
ax2.set_ylabel('Rate')
lines = ax.get_lines() + ax2.get_lines()
lgd = ax.legend(lines, [line.get_label() for line in lines],
loc='lower center', ncol=2, bbox_to_anchor=(0.5, -0.15),
frameon=False)
ax.set_title('Economic Rate and Index',
weight='bold')
for i in range(5):
plt.axvspan(Dates['Peak'][i], Dates['Trough'][i],
facecolor='grey', alpha=0.5)
plt.grid(False)
plt.savefig('C:\\test.pdf',
bbox_extra_artists=(lgd,), bbox_inches='tight')
I am having a hard time to reproduce this figure in a subplot (2X2). The only thing I would change in each of the subplots is the blue line (X1 in df... for X2, X3...). How can I have a 2X2 subplot of the above graph? Of Course I would only keep one legend at the bottom of the subplots. Thanks for the help.
The data is here and the "Dates" to reproduce the gray bars here.
This is how you could create a 2x2 raster with twinx each:
import matplotlib.pyplot as plt
fig, ((ax1a, ax2a), (ax3a, ax4a)) = plt.subplots(2, 2)
ax1b = ax1a.twinx()
ax2b = ax2a.twinx()
ax3b = ax3a.twinx()
ax4b = ax4a.twinx()
ax1a.set_ylabel('ax1a')
ax2a.set_ylabel('ax2a')
ax3a.set_ylabel('ax3a')
ax4a.set_ylabel('ax4a')
ax1b.set_ylabel('ax1b')
ax2b.set_ylabel('ax2b')
ax3b.set_ylabel('ax3b')
ax4b.set_ylabel('ax4b')
plt.tight_layout()
plt.show()
Result:

Categories