Curious Matplotlib tick label alignment - python

This code:
import numpy as np
import matplotlib.pyplot as plt
letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
x = range(26)
v = np.random.random(26)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar(x, v, width=0.8, align='center')
ax.set_xticks(x)
ax.set_xticklabels(letters)
plt.savefig('so.eps')
Generates the figure below:
As you can see, the 'Q' is not aligned with the baseline properly and looks wrong.
Can anyone shed any light on this? If it's a bug in Matplotlib, is there a hack to get round it (e.g. by realigning a single xtick label)?
I have text.usetex : True in my matplotlibrc file, and the problem only seems to show when I save the figure as eps.

Related

How to remove ticklabels on a histogram with log scale

The following code does not remove yticklabels while it should since there is ax.set_yticklabels([]).
import numpy as np
import matplotlib.pyplot as plt
data = np.random.standard_normal(10)
fig = plt.figure()
ax = plt.axes()
ax.hist(data)
ax.set_yscale('log')
ax.set_yticklabels([])
Note: if changing 10 by 100 in data = np.random.standard_normal(10), the yticklabels are correctly removed...
Is this a bug to report? If so, how (and where) to report it?
Is there another way to remove those yticklabels?
Many thanks for your help!
you can hide like below:
ax.axes.get_xaxis().set_visible(False)
ax.axes.get_yaxis().set_visible(False)

formatting ticks on pyplot cmap loses the plot

Using the following code:-
fig=plt.figure()
#ax = fig.add_subplot(111)
ax=plt.axes()
font0 = FontProperties()
outgrid=[[x*y for x in range(testXaxis)] for y in range (levIndRange)]
vmin=0
vmax=testXaxis*levIndRange
height = [v*1000.5 for v in range (levMaxInd)]
colours='terrain'
cmap=plt.cm.get_cmap(colours)
norm=matplotlib.colors.Normalize(clip=False,vmin=vmin,vmax=vmax)
print 'vmax = ',vmax
m=plt.cm.ScalarMappable(cmap=cmap,norm=norm)
m.set_array(outgrid)
plt.imshow(np.flipud(outgrid),cmap=cmap, norm=norm, aspect=stretch)
#ax.imshow(np.flipud(outgrid),cmap=cmap, norm=norm, aspect=stretch)
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
#plt.axis.YAxis.set_major_formatter(FormatStrFormatter('%.0f')) # 'module' object has no attribute 'set_major_formatter'
plt.yticks([s for s in range(0,levIndRange,levParInt)],[height[v] for v in range(levMinInd-1,levMaxInd-1,levParInt)])
plt.xticks([1,3,5,7,9,11,13,15,17,19])
#ax.xaxis.set_ticks([1,3,5,7,9,11,13,15,17,19])
#ax.yaxis.set_ticks([height[v] for v in range(levMinInd-1,levMaxInd-1,levParInt)]) # This one line makes the plot collapse
plt.ylabel(yLabel)
plt.xlabel(xLabel)
I get the following plot, which is fine, but I want to change the floating point precision on the y-axis:-
So, when I try to alter the precision on the y-axis using set_major_formatter and the following lines instead of plot.yticks :-
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
ax.xaxis.set_ticks([1,3,5,7,9,11,13,15,17,19])
ax.yaxis.set_ticks([height[v] for v in range(levMinInd-1,levMaxInd-1,levParInt)]) # This one line makes the plot collapse
... the plot disappears:-
How can I alter the precision without losing the plot?
Any help gratefully received.
Thanks
I am answering rather than editing because I have solved the lost plot problem, and that might be a help to someone else. The solution is to move the plt.imshow line AFTER the ax.yaxis.set_ticks line. However, I am still not getting the expected Y axis ticks with no decimal point.
The first block of code below produces a plot with Y ticks: 0.0,1000.5,2001.0,3001.5,4002.0
import matplotlib
import matplotlib.pyplot as plt
outgrid=[[x*y for x in range(4)] for y in range (5)]
height = [v*1000.5 for v in range (5)]
cmap=plt.cm.get_cmap('terrain')
norm=matplotlib.colors.Normalize(clip=False)
m=plt.cm.ScalarMappable(cmap=cmap,norm=norm)
m.set_array(outgrid)
plt.imshow(outgrid,cmap=cmap, norm=norm, aspect=0.5)
plt.yticks([s for s in range(5)],[height[t] for t in range(5)])
plt.show()
This second block of code tries to format these ticks with no decimal point but just produces one Y tick of 0
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.ticker import FormatStrFormatter
ax=plt.axes()
outgrid=[[x*y for x in range(4)] for y in range (5)]
height = [v*1000.5 for v in range (5)]
cmap=plt.cm.get_cmap('terrain')
norm=matplotlib.colors.Normalize(clip=False)
m=plt.cm.ScalarMappable(cmap=cmap,norm=norm)
m.set_array(outgrid)
ax.yaxis.set_major_formatter(FormatStrFormatter('%.0f'))
ax.yaxis.set_ticks([height[t] for t in range(5)])
plt.imshow(outgrid,cmap=cmap, norm=norm, aspect=0.5)
plt.show()

How to properly display sufficient tick markers using plt.savefig?

After running the code below, the axis tick markers all overlap with each other. At this time, each marker could still have good resolution when zooming popped up by plt.show(). However, the figure saved by plt.savefig('fig.png') would lost its resolution. Can this also be optimised?
from matplotlib.ticker import FuncFormatter
from matplotlib.pyplot import show
import matplotlib.pyplot as plt
import numpy as np
a=np.random.random((1000,1000))
# create scaled formatters / for Y with Atom prefix
formatterY = FuncFormatter(lambda y, pos: 'Atom {0:g}'.format(y))
formatterX = FuncFormatter(lambda x, pos: '{0:g}'.format(x))
# apply formatters
fig, ax = plt.subplots()
ax.yaxis.set_major_formatter(formatterY)
ax.xaxis.set_major_formatter(formatterX)
plt.imshow(a, cmap='Reds', interpolation='nearest')
# create labels
plt.xlabel('nanometer')
plt.ylabel('measure')
plt.xticks(list(range(0, 1001,10)))
plt.yticks(list(range(0, 1001,10)))
plt.savefig('fig.png',bbox_inches='tight')
plt.show()
I think you can solve it by setting the size of the figure, e.g.
fig, ax = plt.subplots()
fig.set_size_inches(15., 15.)
As pointed out by #PatrickArtner in the comments, you can then also avoid the overlap of x-ticks by
plt.xticks(list(range(0, 1001, 10)), rotation=90)
instead of
plt.xticks(list(range(0, 1001,10)))
The rest of the code is completely unchanged; the output then looks reasonable (but is too large to upload here).

matplotlib: how to simultaneously change tick position and figure shape

I'm plotting a figure and hope to set the figure shape and tick positions. But I find that I cannot do the two things together. For example, if I use the following code:
import matplotlib
import matplotlib.pyplot as plt
ls = range(0,10)
fig, ax = plt.subplots()
# set figure shape
plt.figure(figsize=(10,5))
plt.ylim([0,10])
plt.plot(ls)
figname = 'aaa.jpg'
# set ytick positions
ax.set_yticks([1,3,5,7,9])
plt.savefig(figname,format='jpg')
Then I get the following figure.
The shape is correct. But the ytick is not changed by the code line ax.set_yticks([1,3,5,7,9]).
Then I try the following code (i.e. move the sentence plt.figure(figsize=(10,5)) to the beginning of the program):
import matplotlib
import matplotlib.pyplot as plt
# set figure shape
plt.figure(figsize=(10,5))
ls = range(0,10)
fig, ax = plt.subplots()
plt.ylim([0,10])
plt.plot(ls)
figname = 'aaa.jpg'
# set ytick position
ax.set_yticks([1,3,5,7,9])
plt.savefig(figname,format='jpg')
Then I get the following figure:
The ytick is correct. Yicks appear in positions [1,3,5,7,9]. However, the figure shape is not the shape I set.
How to do the two things together?
Thank you all for helping me!!!
you can set the figsize in the subplot function instead.
what went wrong in the first graph:
plt.figure(figsize=(10,5))
the above line of code is creating a new figure on which your graph is being plotted, the 'ax' on which you are setting the y ticks is related to a subplot which is different.
ls = range(0,10)
fig, ax = plt.subplots(figsize=(10,5))
ax.set_yticks([1,3,5,7,9])
ax.set_xticks([1,3,5,7,9])
plt.grid()
plt.plot(ls)
The plot is showing exactly what you're trying to do

matplotlib: plotting histogram plot just above scatter plot

I would like to make beautiful scatter plots with histograms above and right of the scatter plot, as it is possible in seaborn with jointplot:
I am looking for suggestions on how to achieve this. In fact I am having some troubles in installing pandas, and also I do not need the entire seaborn module
I encountered the same problem today. Additionally I wanted a CDF for the marginals.
Code:
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
x = np.random.beta(2,5,size=int(1e4))
y = np.random.randn(int(1e4))
fig = plt.figure(figsize=(8,8))
gs = gridspec.GridSpec(3, 3)
ax_main = plt.subplot(gs[1:3, :2])
ax_xDist = plt.subplot(gs[0, :2],sharex=ax_main)
ax_yDist = plt.subplot(gs[1:3, 2],sharey=ax_main)
ax_main.scatter(x,y,marker='.')
ax_main.set(xlabel="x data", ylabel="y data")
ax_xDist.hist(x,bins=100,align='mid')
ax_xDist.set(ylabel='count')
ax_xCumDist = ax_xDist.twinx()
ax_xCumDist.hist(x,bins=100,cumulative=True,histtype='step',density=True,color='r',align='mid')
ax_xCumDist.tick_params('y', colors='r')
ax_xCumDist.set_ylabel('cumulative',color='r')
ax_yDist.hist(y,bins=100,orientation='horizontal',align='mid')
ax_yDist.set(xlabel='count')
ax_yCumDist = ax_yDist.twiny()
ax_yCumDist.hist(y,bins=100,cumulative=True,histtype='step',density=True,color='r',align='mid',orientation='horizontal')
ax_yCumDist.tick_params('x', colors='r')
ax_yCumDist.set_xlabel('cumulative',color='r')
plt.show()
Hope it helps the next person searching for scatter-plot with marginal distribution.
Here's an example of how to do it, using gridspec.GridSpec:
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import numpy as np
x = np.random.rand(50)
y = np.random.rand(50)
fig = plt.figure()
gs = GridSpec(4,4)
ax_joint = fig.add_subplot(gs[1:4,0:3])
ax_marg_x = fig.add_subplot(gs[0,0:3])
ax_marg_y = fig.add_subplot(gs[1:4,3])
ax_joint.scatter(x,y)
ax_marg_x.hist(x)
ax_marg_y.hist(y,orientation="horizontal")
# Turn off tick labels on marginals
plt.setp(ax_marg_x.get_xticklabels(), visible=False)
plt.setp(ax_marg_y.get_yticklabels(), visible=False)
# Set labels on joint
ax_joint.set_xlabel('Joint x label')
ax_joint.set_ylabel('Joint y label')
# Set labels on marginals
ax_marg_y.set_xlabel('Marginal x label')
ax_marg_x.set_ylabel('Marginal y label')
plt.show()
I strongly recommend to flip the right histogram by adding these 3 lines of code to the current best answer before plt.show() :
ax_yDist.invert_xaxis()
ax_yDist.yaxis.tick_right()
ax_yCumDist.invert_xaxis()
The advantage is that any person who is visualizing it can compare easily the two histograms just by moving and rotating clockwise the right histogram on their mind.
On contrast, in the plot of the question and in all other answers, if you want to compare the two histograms, your first reaction is to rotate the right histogram counterclockwise, which leads to wrong conclusions because the y axis gets inverted. Indeed, the right CDF of the current best answer looks decreasing at first sight:

Categories

Resources