I want to access the tick labels on my matplotlib colobar, so that I can manipulate them.
My starting labels may be [-2,-1,0,1,2] for example.
I have used:
locs,oldlabels = plt.xticks()
newlabels = ['a','b','c','d','e']
plt.xticks(locs, newlabels)
This works. But I don't want to manually write in the new labels. I want to access the oldlabels, so that I can have the newlabels as say [2*(-2), 2*(-1), 2*0, 2*1, 2*2].
I just don't know how to 'get at' the oldlabels. I googled everything and tried lots of things, but I'm doing something fundamentally wrong.
I tried to print oldlabels[0], but I get Text(0,0,u'\u22122.0').
EDIT:
I'm currently doing:
new_labels = [1,2,3,4,5,6,7,8,9]
colorbarname.ax.set_xticklabels(new_labels)
which works. But I want to set them as 2 x their old value. How can I do this automatically? I need to extract the old label values, multiply by (say) 2, update the axis labels with the new values.
If your data is not confined to [0,1], I'd recommend using a norm when you pass the data to the colormap instead of changing the data and relabeling the colorbar: http://matplotlib.org/api/cm_api.html?highlight=norm%20colormap#matplotlib.cm.ScalarMappable.norm
However, you can relabel the colorbar by manipulating the underlying axis directly:
import numpy as np
import pylab as plt
A = np.random.random((10,10))
plt.subplot(121)
plt.imshow(A,interpolation='nearest')
cb = plt.colorbar()
oldlabels = cb.ax.get_yticklabels()
print(map(lambda x: x.get_text(),oldlabels))
newlabels = map(lambda x: str(2 * float(x.get_text())), oldlabels)
print(newlabels)
cb.ax.set_yticklabels(newlabels)
plt.show()
oh, and now I find the matplotlib gallery example, nearly the same: http://matplotlib.org/examples/pylab_examples/colorbar_tick_labelling_demo.html
Related
I am having an very hard time getting the ticklabels of a seaborn heatmap to show only single integers (i.e. no floating numbers). I have two lists that form the axes of a data frame that i plot using seaborn.
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.ticker as tkr
x = np.linspace(0, 15, 151)
y = np.linspace(0, 15, 151)
#substitute random data for my_data
df_map = pd.DataFrame(my_data, index = y, columns = x)
plt.figure()
ax = sns.heatmap(df_map, square = True, xticklabels = 20, yticklabels = 20)
ax.invert_yaxis()
I've reviewed many answers and the documents. My biggest problem is I have little experience and a very poor understanding of matplotlib and the docs feel like a separate language... Here are the things I've tried.
ATTEMPT 1: A slightly modified version of the solution to this question:
fmtr = tkr.StrMethodFormatter('{x:.0f}')
plt.gca().xaxis.set_major_formatter(fmtr)
I'm pretty sure tkr.StrMethodFormatter() is displaying every 20th index of the value it encounters in my axis string, which is probably due to my settings in sns.heatmap(). I tried different string inputs to tkr.StrMethodFormatter() without success. I looked at two other questions and tried different combinations of tkr classes that were used in answers for here and here.
ATTEMPT 2:
fmtr = tkr.StrMethodFormatter("{x:.0f}")
locator = tkr.MultipleLocator(50)
fstrform = tkr.FormatStrFormatter('%.0f')
plt.gca().xaxis.set_major_formatter(fmtr)
plt.gca().xaxis.set_major_locator(locator)
#plt.gca().xaxis.set_major_formatter(fstrform)
And now i'm at a complete loss. I've found out locator changes which nth indices to plot, and both fmtr and fstrform change the number of decimals being displayed, but i cannot for the life of me get the axes to display the integer values that exist in the axes lists!
Please help! I've been struggling for hours. It's probably something simple, and thank you!
As an aside:
Could someone please elaborate on the documentation excerpt in that question, specifically:
...and the field used for the position must be labeled pos.
Also, could someone please explain the differences between tkr.StrMethodFormatter("{x:.0f}") and tkr.FormatStrFormatter('%.0f')? I find it annoying there are two ways, each with their own syntax, to produce the same result.
UPDATE:
It took me a while to get around to implementing the solution provided by #ImportanceOfBeingErnest. I took an extra precaution and rounded the numbers in the x,y arrays. I'm not sure if this is necessary, but I've produced the result I wanted:
x = np.linspace(0, 15, 151)
y = np.linspace(0, 15, 151)
# round float numbers in axes arrays
x_rounded = [round(i,3) for i in x]
y_rounded = [round(i,3) for i in y]
#substitute random data for my_data
df_map = pd.DataFrame(my_data, index = y_rounded , columns = x_rounded)
plt.figure()
ax0 = sns.heatmap(df_map, square = True, xticklabels = 20)
ax0.invert_yaxis()
labels = [label.get_text() for label in ax0.get_xticklabels()]
ax0.set_xticklabels(map(lambda x: "{:g}".format(float(x)), labels))
Although I'm still not entirely sure why this worked; check the comments between me and them for clarification.
The sad thing is, you didn't do anything wrong. The problem is just that seaborn has a very perculiar way of setting up its heatmap.
The ticks on the heatmap are at fixed positions and they have fixed labels. So to change them, those fixed labels need to be changed. An option to do so is to collect the labels, convert them back to numbers, and then set them back.
labels = [label.get_text() for label in ax.get_xticklabels()]
ax.set_xticklabels(map(lambda x: "{:g}".format(float(x)), labels))
labels = [label.get_text() for label in ax.get_yticklabels()]
ax.set_yticklabels(map(lambda x: "{:g}".format(float(x)), labels))
A word of caution: One should in principle never set the ticklabels without setting the locations as well, but here seaborn is responsible for setting the positions. We just trust it do do so correctly.
If you want numeric axes with numeric labels that can be formatted as attempted in the question, one may directly use a matplotlib plot.
import numpy as np
import seaborn as sns # seaborn only imported to get its rocket cmap
import matplotlib.pyplot as plt
my_data = np.random.rand(150,150)
x = (np.linspace(0, my_data.shape[0], my_data.shape[0]+1)-0.5)/10
y = (np.linspace(0, my_data.shape[1], my_data.shape[1]+1)-0.5)/10
fig, ax = plt.subplots()
pc = ax.pcolormesh(x, y, my_data, cmap="rocket")
fig.colorbar(pc)
ax.set_aspect("equal")
plt.show()
While this already works out of the box, you may still use locators and formatters as attempted in the question.
I am creating a plot based on a DataFrame:
cg = sns.clustermap(df_correlations.T)
The problem is that the x and y axis have unwanted labels in it which come from a hierarchical index. Thus I want to try and remove those labels e.g. like this:
ax = cg.fig.gca()
ax.set_xlabel('')
ax.set_ylabel('')
But this has no effect. How can I remove the labels on the x and y axis?
Without a mcve of the issue it's hard to know where the labels come from (I don't know how the dataframe needs to look like such that labels are produced, because by default there should not be any labels.) However, the labels can be set - and therefore also set to an empty string - using the known methods .set_xlabel and .set_ylabel of the heatmap axes of the cluster grid.
So if g is a ClusterGrid instance,
g = sns.clustermap(...)
you can get the heatmap axes via
ax = g.ax_heatmap
and then use any method you like to manipulate this matplotlib axes.
ax.set_xlabel("My Label")
ax.set_ylabel("")
Turn off xticklabel, and yticklabel will address your problem.
sns.clustermap(df,yticklabels=False,xticklabels=False)
try plt.axis('off'), it may solve your problem.
I have a set of ticklabels that are strings on my x axis, and I want to be able to get -> modify -> set them. Say for example I have a plot that looks like this:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(range(1,6), range(5))
plt.xticks(range(1,6), ['a','b','c','d','e']
and I want to change the labels on the x axis to ['(a)','(b)','(c)','(d)','(e)']
what is the simplest/best way to do this? I've tried things like:
labels = ['(%s)' % l for l in ax.xaxis.get_ticklabels()]
ax.xaxis.set_ticklabels(labels)
but ax.xaxis.get_ticklabels() returns matplotlib Text objects as opposed to a list of strings and I'm not sure how to go about modifying them. I also tried using matplotlib.ticker.FuncFormatter but could only get a hold of the numeric positions not the labels themselves. Any would be appreciated.
One more layer to unpeel:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(range(1,6), range(5))
plt.xticks(range(1,6), ['a','b','c','d','e'])
labels = ['(%s)' % l.get_text() for l in ax.xaxis.get_ticklabels()]
ax.xaxis.set_ticklabels(labels)
your code but with l.get_text() in the list comp where there was a l.
I am trying to change the value of the ticks on the x-axis an imshow plot using the following code:
import matplotlib.pyplot as plt
import numpy as np
def scale_xaxis(number):
return(number+1001)
data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto')
ax.autoscale(False)
xticks = ax.get_xticks()
ax.xaxis.set_ticklabels(scale_xaxis(xticks))
plt.savefig("test.png")
Resulting image http://ubuntuone.com/2Y5ujtlEkEnrlTcVUxvWLU
However the x-ticks overlap and have "non-round" values. Is there some way for matplotlib to automatically do this? Either by using set_ticklabels or some other way?
Also look into using extent (doc) to let matplotlib do all the thinking about how to put in the tick labels and add in an arbitrary shift:
data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto',extent=[10000,10010,0,1])
If you definitely want do to it my hand, you might be better off setting the formatter and locator of the axis to get what you want (doc).
import matplotlib.pyplot as plt
import numpy as np
def scale_xaxis(number):
return(number+1001)
def my_form(x,pos):
return '%d'%scale_xaxis(x)
data = np.array([range(10),range(10,20)])
fig = plt.figure(figsize=(3,5))
ax = fig.add_subplot(111)
ax.imshow(data,aspect='auto')
ax.autoscale(False)
ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(int(2)))
ax.xaxis.set_major_formatter(matplotlib.ticker.FuncFormatter(my_form))
The locator needs to be set to make sure that ticks don't get put at non-integer locations which are then forcible cast to integers by the formatter (which would leave them in the wrong place)
related questions:
matplotlib: format axis offset-values to whole numbers or specific number
removing leading 0 from matplotlib tick label formatting
There are several ways to do this.
You can:
Pass in an array of ints instead of an array of floats
Pass in an array of formatted strings
Use a custom tick formatter
The last option is overkill for something this simple.
As an example of the first option, you'd change your scale_xaxis function to be something like this:
def scale_xaxis(numbers):
return numbers.astype(int) + 1001
Note that what you're getting out of ax.get_xticks is a numpy array instead of a single value. Thus, we need to do number.astype(int) instead of int(number).
Alternately, we could return a series of formatted strings. set_xticklabels actually expects a sequence of strings:
def scale_xaxis(numbers):
return ['{:0.0f}'.format(item + 1001) for item in numbers]
Using a custom tick formatter is overkill here, so I'll leave it out for the moment. It's quite handy in the right situation, though.
Matplotlib newbie here.
I have the following code:
from pylab import figure, show
import numpy
fig = figure()
ax = fig.add_subplot(111)
plot_data=[1.7,1.7,1.7,1.54,1.52]
xdata = range(len(plot_data))
labels = ["2009-June","2009-Dec","2010-June","2010-Dec","2011-June"]
ax.plot(xdata,plot_data,"b-")
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels)
ax.set_yticks([1.4,1.6,1.8])
fig.canvas.draw()
show()
When you run that code, the resulting chart has a run-in with the first tick label (2009-June) and the origin. How can I get the graph to move over to make that more readable? I tried to put dummy data in, but then Matplotlib (correctly) treats that as data.
add two limits to the x and y axes to shift the tick labels a bit.
# grow the y axis down by 0.05
ax.set_ylim(1.35, 1.8)
# expand the x axis by 0.5 at two ends
ax.set_xlim(-0.5, len(labels)-0.5)
the result is
Because tick labels are text objects you can change their alignment. However to get access to the text properties you need to go through the set_yticklabels function. So add the line:
ax.set_yticklabels([1.4,1.6,1.8],va="bottom")
after your set_yticks call. Alternatively if you go through the pylab library directly, instead of accessing the function through the axes object, you can just set that in one line:
pylab.yticks([1.4,1.6,1.8],va="bottom")
I suggest change Y axis limits:
ax.set_ylim([1.2, 1.8])