I'm very new to using matplotlib, and I'm having difficulty with the xticks. I basically have an x axis from 0 to 0.025. My problem arises since the precision of the most precise value in the x axis seems to set the precision for them all, so e.g. 0 appears as 0.000. I'd like it to appear as 0 since the trailing zeroes are redundant and analogously for the other values.
Here is what I have... the output gives too many trailing zeroes on the x axis:
from matplotlib import rc
from matplotlib import pyplot
import matplotlib.pyplot as plt
rc('font', **{'family': 'serif', 'serif': ['Computer Modern']})
rc('text', usetex = True)
xmin=0
xmax=0.4
ymin=4.0
ymax=4.5
asq=[0.0217268]
mb=[4.1929]
mberr=[0.0055]
# some arguments for points etc...
ebargs = dict(mfc='None',alpha=1,ms=8,
capsize=1.75,elinewidth=0.75,mew=0.75)
fw = 4.5 # width
fh = fw/1.618 # height
plt.rc('figure',figsize=(fw,fh))
plt.xlim(xmin,xmax)
plt.ylim(ymin,ymax)
plt.errorbar(x=[x for x in asq],
y=[y for y in mb],
yerr=[yerr for yerr in mberr],
fmt='o',c='b',mec='b', **ebargs
)
plt.savefig("mb-plot.pdf",bbox_inches='tight')
Is there an obvious way to do what I'd like, or am I stuck with it? I used PyX previously (and I must admit I'm getting a bit muddled as I've learned to use each purely through the use of stuff my collaborators have used and they've varied between), which sets the axes properly, but doesn't seem to support LaTeX as well as I'd like, so it's not an idea solution.
What you need are these two lines:
from matplotlib.ticker import FormatStrFormatter
plt.gca().xaxis.set_major_formatter(FormatStrFormatter('%g'))
The FormatStrFormatter can accept other sprintf-like formatting options.
Related
I noticed a 'strange' behaviour when running the following code:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)
freqs = np.logspace(2,4)
freqs_ext = np.logspace(2, 10)
fig, ax = plt.subplots(1,2)
ax [0].plot(freqs , freqs**2)
#ax[0].xaxis.set_minor_locator(AutoMinorLocator(5))
ax[0].grid(which='both')
#ax[0].minorticks_on()
ax[0].set_xscale( 'log')
ax[1].plot(freqs_ext,freqs_ext**2)
#ax[l].xaxis.set_minor_locator(AutoMinorLocator(5))
ax[1].grid(which='both')
#ax[1].minorticks on()
ax[1].set_xscale('log')
The output is the following:
I have tried more variants than I care to report, (some are commented out in the code above), but I cannot get matplotlib to draw minor gridlines for the plot on the right side, as it does for the one on the left.
I think I have understood that the "problem" lies in where the ticks are located for the second plot, which has a much larger span. They are every two decades and I believe this might be the source of the minor grid lines not displaying.
I have played with xaxis.set_xticks and obtained ticks every decade, but still cannot get this to correctly produce the gridlines.
It is probably something stupid but I can't see it.
NOTE : I know that matplotlib doesn't turn the minor ticks on by default, and in this case this action is "triggered" by changing the scale to log (that's why axis.grid(which='both') actually only acts on the x axis)
OK, I have found this answer:
Matplotlib: strange double-decade axis ticks in log plot
which actually shows how the issue is a design choice for matplotlib starting with v2. Answer was given in 2017 so, not the newest issue :)
The following code correctly plots the minor grids as wanted:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.ticker import LogLocator
freqs = np.logspace(2,4)
freqs_ext = np.logspace(2, 10)
fig, ax = plt.subplots(1,2)
ax[0].plot(freqs , freqs**2)
ax[0].grid(which='both')
ax[0].set_xscale( 'log')
ax[1].plot(freqs_ext,freqs_ext**2)
ax[1].set_xscale('log')
ax[1].xaxis.set_major_locator(LogLocator(numticks=15))
ax[1].xaxis.set_minor_locator(LogLocator(numticks=15,subs=np.arange(2,10)))
ax[1].grid(which='both')
My trace file can be downloaded from here.
When I plot only y axis in log scale. everything is fine
import pandas as pd
import numpy
import matplotlib.pyplot as plt
iplevel = pd.read_csv('iplevel.csv')
fig = plt.figure()
#plt.xscale('log')
plt.yscale('log')
plt.title(' Size Vs Duration (at IP level) for ')
plt.xlabel('Duration (in seconds)')
plt.ylabel('Size (in bytes)')
plt.scatter(iplevel['Time'], iplevel['Length'])
fig.tight_layout()
fig.savefig('iplevel_timevdur.png', dpi=fig.dpi)
When I plot both x and y axis in log scale, something strange happens
import pandas as pd
import numpy
import matplotlib.pyplot as plt
iplevel = pd.read_csv('iplevel.csv')
fig = plt.figure()
plt.xscale('log')
plt.yscale('log')
plt.title(' Size Vs Duration (at IP level) for ')
plt.xlabel('Duration (in seconds)')
plt.ylabel('Size (in bytes)')
plt.scatter(iplevel['Time'], iplevel['Length'])
fig.tight_layout()
fig.savefig('iplevel_timevdur.png', dpi=fig.dpi)
I am not sure where I am going wrong. Any ideas/suggestions welcome
It looks like you have some zeros in your X values. log(0) isn't defined, log(veryclosetozero) is 10^{-verymuch}.
Edit:
In addition, float representation of numbers isn't always completely exact, so 0.0 might end up being stored as 0.00000000000000000001 or similar. The log function would not throw an error in that case, but simply calculate the logarithm of something very very small.
I faced a similar problem when plotting numbers containing a lot of zeros. If your number is represented like 10E-38 format in the csv file, try multiplying all the rows by 1 and then read the data using pandas.
This solved the problem in my case.
I work on a plot in python using the matplot library. The numbers which I have to generate are very big, so also the ticks on the axes are a large numbers and take a lot of space. I was trying to present them as a powers (for example instead having a tick 100000000 I want to have 10^8). I used command: ax.ticklabel_format(style='sci', axis='x', scilimits=(0,4)) however this only created something like this
Is there any other solution to have ticks for the plot as: 1 x 10^4, 2 x 10^4, etc or write the value 1e4 as 10^4 at the end of the label's ticks?
You can use the matplotlib.ticker module, and set the ax.xaxis.set_major_formatter to a FuncFormatter.
For example:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
plt.rcParams['text.usetex'] = True
fig,ax = plt.subplots(1)
x = y = np.arange(0,1.1e4,1e3)
ax.plot(x,y)
def myticks(x,pos):
if x == 0: return "$0$"
exponent = int(np.log10(x))
coeff = x/10**exponent
return r"${:2.0f} \times 10^{{ {:2d} }}$".format(coeff,exponent)
ax.xaxis.set_major_formatter(ticker.FuncFormatter(myticks))
plt.show()
Note, this uses LaTeX formatting (text.usetex = True) to render exponents in the tick labels. Also note the double braces required to differentiate the LaTeX braces from the python format string braces.
There might be a better solution, but if you know the values of each xtick, you can also manually name them.
Here is an example:
http://matplotlib.org/examples/ticks_and_spines/ticklabels_demo_rotation.html
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 want to format my y axis using matplotlib in python 2.7. This is what I tried:
ax.yaxis.get_major_formatter().set_useLocale()
to format my y axis using . as thousands separator. Instead of having 10000, I'd like to have 10.000, and so on... but I can't find any example on how this work...
I could not find the documentation, on this page here there is no example or further documentation: http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.ScalarFormatter.set_useLocale
Or any other idea on how to format my axis?
thanks
I believe that you are looking for more control than perhaps set_useLocale() can offer. Therefore, drawing upon the example given here, I've used FuncFormatter with a simple function. The comma_format function inserts the y-axis labels with a comma as a thousands separator and then replaces the commas with periods. In this way, the y-axis labels can be formatted rather easily.
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
def comma_format(x, p):
return format(x, "6,.0f").replace(",", ".")
ax = subplot(111)
xx = np.arange(0,20,1)
yy = np.arange(1000,10000,450)
ax.get_yaxis().set_major_formatter(ticker.FuncFormatter(comma_format))
plt.scatter(xx,yy)
plt.show()