Changing alpha value of ticklabels without specifying text - python

Matplotlib allows changing the alpha value of almost anything, but how does it work for an ticklabel?
If I have a text, it is easy:
ax.set_xticklabel(labels, alpha=alpha)
The case is different if I do not have a text as the following throws a TypeError, due to missing labels.
ax.set_xticklabel(alpha=alpha)
Therefore, my next idea was to get the automatically generated ticklabels and use them to do the job:
labels = [label.get_text() for label in ax.get_xticklabels()]
ax.set_xticklabels(labels, alpha=alpha
The problem here is, the labels are empty due to the dynamic nature of matplotlib (see here).
So, is there an easy way to change the alpha of my ticklabels without knowing the text beforehand?

It is probably not desirable to set the ticklabels themselves, if you want to change their color. The reason is that setting the labels via ax.set_ticklabels changes the formatter to a FixedFormatter; with this one would loose the automatic formatting behaviour.
Instead change the alpha of the text objects that later constitute the ticklabels. To this end plt.setp is a useful feature.
plt.setp(ax.get_xticklabels(), alpha=0.3)
The same can be achieved via
for t in ax.get_xticklabels():
t.set_alpha(0.3)

Related

zorder value to force grid to background [duplicate]

In Matplotlib, I make dashed grid lines as follows:
fig = pylab.figure()
ax = fig.add_subplot(1,1,1)
ax.yaxis.grid(color='gray', linestyle='dashed')
however, I can't find out how (or even if it is possible) to make the grid lines be drawn behind other graph elements, such as bars. Changing the order of adding the grid versus adding other elements makes no difference.
Is it possible to make it so that the grid lines appear behind everything else?
According to this - http://matplotlib.1069221.n5.nabble.com/axis-elements-and-zorder-td5346.html - you can use Axis.set_axisbelow(True)
(I am currently installing matplotlib for the first time, so have no idea if that's correct - I just found it by googling "matplotlib z order grid" - "z order" is typically used to describe this kind of thing (z being the axis "out of the page"))
To me, it was unclear how to apply andrew cooke's answer, so this is a complete solution based on that:
ax.set_axisbelow(True)
ax.yaxis.grid(color='gray', linestyle='dashed')
If you want to validate the setting for all figures, you may set
plt.rc('axes', axisbelow=True)
or
plt.rcParams['axes.axisbelow'] = True
It works for Matplotlib>=2.0.
I had the same problem and the following worked:
[line.set_zorder(3) for line in ax.lines]
fig.show() # to update
Increase 3to a higher value if it does not work.
You can also set the zorder kwarg in matplotlib.pyplot.grid
plt.grid(which='major', axis='y', zorder=-1.0)
You can try to use one of Seaborn's styles. For instance:
import seaborn as sns
sns.set_style("whitegrid")
Not only the gridlines will get behind but the looks are nicer.
For some (like me) it might be interesting to draw the grid behind only "some" of the other elements. For granular control of the draw order, you can use matplotlib.artist.Artist.set_zorder on the axes directly:
ax.yaxis.grid(color='gray', linestyle='dashed')
ax.set_zorder(3)
This is mentioned in the notes on matplotlib.axes.Axes.grid.

Why is set_xlim() not setting the x-limits in my figure?

I'm plotting some data with matplotlib. I want the plot to focus on a specific range of x-values, so I'm using set_xlim().
Roughly, my code looks like this:
fig=plt.figure()
ax=fig.add_subplot(111)
for ydata in ydatalist:
ax.plot(x_data,y_data[0],label=ydata[1])
ax.set_xlim(left=0.0,right=1000)
plt.savefig(filename)
When I look at the plot, the x range ends up being from 0 to 12000. This occurs whether set_xlim() occurs before or after plot(). Why is set_xlim() not working in this situation?
Out of curiosity, what about switching in the old xmin and xmax?
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x_data,y_data)
ax.set_xlim(xmin=0.0, xmax=1000)
plt.savefig(filename)
The text of this answer was taken from an answer that was deleted almost immediately after it was posted.
set_xlim() limits the data that is displayed on the plot.
In order to change the bounds of the axis, use set_xbound().
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot(x_data,y_data)
ax.set_xbound(lower=0.0, upper=1000)
plt.savefig(filename)
In my case the following solutions alone did not work:
ax.set_xlim([0, 5.00])
ax.set_xbound(lower=0.0, upper=5.00)
However, setting the aspect using set_aspect worked, i.e:
ax.set_aspect('auto')
ax.set_xlim([0, 5.00])
ax.set_xbound(lower=0.0, upper=5.00)
I have struggled a lot with the ax.set_xlim() and couldn't get it to work properly and I found out why exactly. After setting the xlim I was setting the xticks and xticklabels (those are the vertical lines on the x-axis and their labels) and this somehow elongated the axis to the needed extent. So if the last tick was at 300 and my xlim was set at 100, it again widened the axis to the 300 just to place the tick there.
So the solution was to put it just after the troublesome code:
ax.set_xlabel(label)
ax.set_xticks(xticks)
ax.set_xticklabels(xticks, rotation=60)
ax.set_xlim(xmin=0.0, xmax=100.0)
The same thing occurred to me today. My issue was that the data was not in the right format, i.e. not floats. The limits I set (itself floats) became meaningless compared to e.g. strings. After putting float() around the data, everything worked as expected.

Show only the n'th ticklabel in a pandas boxplot

I am new to pandas and matplotlib, but not to Python. I have two questions; a primary and a secondary one.
Primary:
I have a pandas boxplot with FICO score on the x-axis and interest rate on the y-axis.
My x-axis is all messed up since the FICO scores are overwriting each other.
I'd like to show only every 4th or 5th ticklabel on the x-axis for a couple of reasons:
in general it's less chart-junky
in this case it will allow the labels to actually be read.
My code snippet is as follows:
plt.figure()
loansmin = pd.read_csv('../datasets/loanf.csv')
p = loansmin.boxplot('Interest.Rate','FICO.Score')
I saved the return value in p as I thought I might need to manipulate the plot further which I do now.
Secondary:
How do I access the plot, subplot, axes objects from pandas boxplot.
p above is an matplotlib.axes.AxesSubplot object.
help(matplotlib.axes.AxesSubplot) gives a message saying:
'AttributeError: 'module' object has no attribute 'AxesSubplot'
dir(matplotlib.axes) lists Axes, Subplot and Subplotbase as in that namespace but no AxesSubplot. How do I understand this returned object better?
As I explored further I found that one could explore the returned object p via dir().
Doing this I found a long list of useful methods, amongst which was set_xticklabels.
Doing help(p.set_xticklabels) gave some cryptic, but still useful, help - essentially suggesting passing in a list of strings for ticklabels.
I then tried doing the following - adding set_xticklabels to the end of the last line in the above code effectively chaining the invocations.
plt.figure()
loansmin = pd.read_csv('../datasets/loanf.csv')
p=loansmin.boxplot('Interest.Rate','FICO.Score').set_xticklabels(['650','','','','','700'])
This gave the desired result. I suspect there's a better way as in the way matplotlib does it which allows you to show every n'th label. But for immediate use this works, and also allows setting labels where they are not periodic for whatever reason, if you need that.
As usual, writing out the question explicitly helped me find the answer. And if anyone can help me get to the underlying matplotlib object that is still an open question.
AxesSubplot (I think) is just another way to get at the Axes in matplotlib. set_xticklabels() is part of the matplotlib object oriented interface (on axes). So, if you were using something like pylab, you might use xticks(ticks, labels), but instead here you have to separate it into different calls ax.set_xticks(ticks), ax.set_xticklabels(labels). (where ax is an Axes object).
Let's say you only want to set ticks at 650 and 700. You could do the following:
ticks = labels = [650, 700]
plt.figure()
loansmin = pd.read_csv('../datasets/loanf.csv')
p=loansmin.boxplot('Interest.Rate','FICO.Score')
p.set_xticks(ticks)
p.set_xticklabels(labels)
Similarly, you can use set_xlim and set_ylim to do the equivalent of xlim() and ylim() in plt.

Matplotlib adding overlay labels to an axis

In matplotlib I wish to know the cleanest and most robust means of overlaying labels onto an axis. This is probably best demonstrated with an example:
While normal axis labels/ticks are placed every 5.00 units additional labels without ticks have been overlayed onto the axis (this can be seen at 1113.75 which partially covers 1114.00 and 1105.00 which is covered entirely). The labels also have the same font and size as their normal, ticked, counterparts with the background (if any) going right up to the axis (as a tick mark would).
What is the simplest way of obtaining this effect in matplotlib?
Edit
Following on from #Ken's suggestion I have managed to obtain the effect for an existing tick/label by using ax.yaxis.get_ticklines and ax.yaxis.get_ticklabels to both remove the tick marker and change the background/font/zorder of a label. However, I am unsure how best to add a new tick/label to an axis.
In other words I am looking for a function add_tick(ax.yaxis, loc) that adds a tick at location loc and returns the tickline and ticklabel objects for me to operate on.
I haven't ever tried to do that, but I think that the Artist tutorial might be helpful for you. In particular, the last section has the following code:
for line in ax1.yaxis.get_ticklines():
# line is a Line2D instance
line.set_color('green')
line.set_markersize(25)
line.set_markeredgewidth(3)
I think that using something like line.set_markersize(0) might make the markers have size zero. The difficult part might be finding the ones that need that done. It is possible that the line.xdata or line.ydata arrays might contain enough information to isolate the ones you need. Of course, if you are manually adding the tick marks, it is possible that as you do that the instance gets returned, so you can just modify them as you create them.
The best solution I have been able to devise:
# main: axis; olocs: locations list; ocols: location colours
def overlay_labels(main, olocs, ocols):
# Append the overlay labels as ticks
main.yaxis.set_ticks(np.append(main.yaxis.get_ticklocs(), olocs))
# Perform generic formatting to /all/ ticks
# [...]
labels = reversed(main.yaxis.get_ticklabels())
markers = reversed(main.yaxis.get_ticklines()[1::2]) # RHS ticks only
glines = reversed(main.yaxis.get_gridlines())
rocols = reversed(ocols)
# Suitably format each overlay tick (colours and lines)
for label,marker,grid,colour in izip(labels, markers, glines, rocols):
label.set_color('white')
label.set_backgroundcolor(colour)
marker.set_visible(False)
grid.set_visible(False)
It is not particularly elegant but does appear to work.

matplotlib set yaxis label size

How can I change the size of only the yaxis label?
Right now, I change the size of all labels using
pylab.rc('font', family='serif', size=40)
but in my case, I would like to make the y-axis label larger than the x-axis. However, I'd like to leave the tick labels alone.
I've tried, for example:
pylab.gca().get_ylabel().set_fontsize(60)
but I only get:
AttributeError: 'str' object has no attribute 'set_fontsize'
So, obviously that doesn't work. I've seen lots of stuff for tick sizes, but nothing for the axis labels themselves.
If you are using the 'pylab' for interactive plotting you can set the labelsize at creation time with pylab.ylabel('Example', fontsize=40).
If you use pyplot programmatically you can either set the fontsize on creation with ax.set_ylabel('Example', fontsize=40) or afterwards with ax.yaxis.label.set_size(40).

Categories