So I am looking to simply format the offset string (at least that is what i think it is called, see image) that matplotlib places along with an axis that has been set to show tick labels in scientific notation, but where the range is less than one order of magnitude (power of 10).
here is what I am talking about:
Essentially, how do I make it bigger/coloured?
you can use ax.yaxis.get_offset_text() to access the offset text. You can then set the size and color on that Text object. For example:
import matplotlib.pyplot as plt
import numpy as np
fig,ax = plt.subplots()
ax.plot(range(10),np.linspace(0,1e11,10))
offset_text = ax.yaxis.get_offset_text()
offset_text.set_size(20)
offset_text.set_color('red')
plt.show()
Related
I have some dataset:
%matplotlib inline
import matplotlib.pyplot as plt
dataset = [28892147.7659855, 28892150.0913124, 28892148.7255983, 28892146.365328,
28892148.101613, 28892147.0887403, 28892147.8564253, 28892146.8626385,
28892146.480244, 28892146.8724146, 28892146.699191, 28892146.405013,
28892146.225238, 28892146.434353, 28892146.3250017, 28892146.344571,
28892146.494564, 28892146.36454, 28892146.8347917, 28892146.20861,
28892146.222876]
plt.plot(dataset)
by what logic matplotlib.pyplot outputs the value of 2.8892100000e7?
By default the ScalarFormatter that is used to set the tick mark labels, will work out an offset value to try and make the tick labels "round" numbers. How the offset is worked out can be found in the _compute_offset method here. How to turn off the offset is shown in the examples here. One way being, e.g.,
plt.plot(dataset)
# get axes object
ax = plt.gca()
# turn off the offset
ax.ticklabel_format(useOffset=False)
I have a line chart based on a simple list of numbers. By default the x-axis is just the an increment of 1 for each value plotted. I would like to be a percentage instead but can't figure out how. So instead of having an x-axis from 0 to 5, it would go from 0% to 100% (but keeping reasonably spaced tick marks. Code below. Thanks!
from matplotlib import pyplot as plt
from mpl_toolkits.axes_grid.axislines import Subplot
data=[8,12,15,17,18,18.5]
fig=plt.figure(1,(7,4))
ax=Subplot(fig,111)
fig.add_subplot(ax)
plt.plot(data)
The code below will give you a simplified x-axis which is percentage based, it assumes that each of your values are spaces equally between 0% and 100%.
It creates a perc array which holds evenly-spaced percentages that can be used to plot with. It then adjusts the formatting for the x-axis so it includes a percentage sign using matplotlib.ticker.FormatStrFormatter. Unfortunately this uses the old-style string formatting, as opposed to the new style, the old style docs can be found here.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mtick
data = [8,12,15,17,18,18.5]
perc = np.linspace(0,100,len(data))
fig = plt.figure(1, (7,4))
ax = fig.add_subplot(1,1,1)
ax.plot(perc, data)
fmt = '%.0f%%' # Format you want the ticks, e.g. '40%'
xticks = mtick.FormatStrFormatter(fmt)
ax.xaxis.set_major_formatter(xticks)
plt.show()
This is a few months late, but I have created PR#6251 with matplotlib to add a new PercentFormatter class. With this class you can do as follows to set the axis:
import matplotlib.ticker as mtick
# Actual plotting code omitted
ax.xaxis.set_major_formatter(mtick.PercentFormatter(5.0))
This will display values from 0 to 5 on a scale of 0% to 100%. The formatter is similar in concept to what #Ffisegydd suggests doing except that it can take any arbitrary existing ticks into account.
PercentFormatter() accepts three arguments, max, decimals, and symbol. max allows you to set the value that corresponds to 100% on the axis (in your example, 5).
The other two parameters allow you to set the number of digits after the decimal point and the symbol. They default to None and '%', respectively. decimals=None will automatically set the number of decimal points based on how much of the axes you are showing.
Note that this formatter will use whatever ticks would normally be generated if you just plotted your data. It does not modify anything besides the strings that are output to the tick marks.
Update
PercentFormatter was accepted into Matplotlib in version 2.1.0.
Totally late in the day, but I wrote this and thought it could be of use:
def transformColToPercents(x, rnd, navalue):
# Returns a pandas series that can be put in a new dataframe column, where all values are scaled from 0-100%
# rnd = round(x)
# navalue = Nan== this
hv = x.max(axis=0)
lv = x.min(axis=0)
pp = pd.Series(((x-lv)*100)/(hv-lv)).round(rnd)
return pp.fillna(navalue)
df['new column'] = transformColToPercents(df['a'], 2, 0)
I am attempting to plot differential cross-sections of nuclear decays and so the magnitudes of the y-axis are around 10^-38 (m^2) pylab as default plots the axis as 0.0,0.2,0.4... etc and has a '1e-38' at the top of the y-axis.
I need to increase the font size of just this little bit, I have tried adjusting the label size
py.tick_params(axis='y', labelsize=20)
but this only adjusts the labels 0.0,0.2,0.4....
Many thanks for all help
You can access the text object using the ax.yaxis.get_offset_text().
import numpy as np
import matplotlib.pyplot as plt
# Generate some data
N = 10
x = np.arange(N)
y = np.array([i*(10**-38) for i in x])
fig, ax = plt.subplots()
# Plot the data
ax.plot(x,y)
# Get the text object
text = ax.yaxis.get_offset_text()
# Set the size.
text.set_size(30) # Overkill!
plt.show()
I've written the solution above using matplotlib.pyplot rather than pylab though if you absolutely have to use pylab then it can be changed (though I'd recommend you use matplotlib.pyplot in any case as they are pretty much identical you can just do a lot more with pyplot easier).
Edit
If you were to use pylab then the code would be:
pylab.plot(x, y)
ax = pylab.gca() # Gets the current axis object
text = ax.yaxis.get_offset_text() # Get the text object
text.set_size(30) # # Set the size.
pylab.show()
An example plot with an (overkill!) offset text.
I have bubble plot like this, and I am willing to put labels next to each bubble (their name). Does any body know how to do that?
#Falko refered to another post that indicates you should be looking for the text method of the axes. However, your problem is quite a bit more involved than that, because you'll need to implement an offset that scales dynamically with the size of the "bubble" (the marker). That means you'll be looking into the transformation methods of matplotlib.
As you didn't provide a simple example dataset to experiment with, I've used one that is freely available: earthquakes of 1974. In this example, I'm plotting the depth of the quake vs the date on which it occurred, using the magnitude of the earthquake as the size of the bubbles/markers. I'm appending the locations of where these earthquakes happened next to the markers, not inside (which is far more easy: ignore the offset and set ha='center' in the call to ax.text).
Note that the bulk of this code example is merely about getting some dataset to toy with. What you really needed was just the ax.text method with the offset.
from __future__ import division # use real division in Python2.x
from matplotlib.dates import date2num
import matplotlib.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
# Get a dataset
data_url = 'http://datasets.flowingdata.com/earthquakes1974.csv'
df = pd.read_csv(data_url, parse_dates=['time'])
# Select a random subset of that dataframe to generate some variance in dates, magnitudes, ...
data = np.random.choice(df.shape[0], 10)
records = df.loc[data]
# Taint the dataset to add some bigger variance in the magnitude of the
# quake to show that the offset varies with the size of the marker
records.mag.values[:] = np.arange(10)
records.mag.values[0] = 50
records.mag.values[-1] = 100
dates = [date2num(dt) for dt in records.time]
f, ax = plt.subplots(1,1)
ax.scatter(dates, records.depth, s=records.mag*100, alpha=.4) # markersize is given in points**2 in recentt versions of mpl
for _, record in records.iterrows():
# Specify an offset for the text annotation:
# it is approx the radius of the disc + 10 points to the right
dx, dy = np.sqrt(record.mag*100)/f.dpi/2 + 10/f.dpi, 0.
offset = transforms.ScaledTranslation(dx, dy, f.dpi_scale_trans)
ax.text(date2num(record.time), record.depth, s=record.place,
va='center', ha='left',
transform=ax.transData + offset)
ax.set_xticks(dates)
ax.set_xticklabels([el.strftime("%Y-%M") for el in records.time], rotation=-60)
ax.set_ylabel('depth of earthquake')
plt.show()
For one such run, I got:
Definitely not pretty because of the overlapping labels, but it was just an example to show how to use the transforms in matplotlib to dynamically add an offset to the labels.
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.