Edit tick labels in logarithmic axis - python-2.7

I'm trying to edit the tick labels but I keep getting scientific notation, even after setting the ticks. Here is a MWE:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(9, 7))
fig.subplots_adjust(left=0.11, right=0.95, top=0.94)
ax.ticklabel_format(style='plain')
plt.plot([1,4],[3,6] )
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xticks([0.7,1,1.5,2,2.5,3,4,5])
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
which produces this plot
As you can see ax.ticklabel_format(style='plain') doesn't seem to work as I keep getting tick labels in scientific notation, and when using ax.set_xticks the old tick labels are still present. I took a look at this topic and it seems like the problem is in the choose of the ticks, if I use for example 0.3 instead of 0.7 as the first tick it works, however I need to do a plot in this specific range and using log scale.
Any work around?

Actually, your code is doing what you need, the problem is the labels from the minor ticks that remain unaffected and overlap with the major ticks
you can simply add the line:
ax.get_xaxis().set_minor_formatter(matplotlib.ticker.NullFormatter())
full code:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(9, 7))
fig.subplots_adjust(left=0.11, right=0.95, top=0.94)
ax.ticklabel_format(style='plain')
plt.plot([1,4],[3,6] )
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_xticks([0.7,1,1.5,2,2.5,3,4,5])
ax.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter())
ax.get_xaxis().set_minor_formatter(matplotlib.ticker.NullFormatter())

Related

PyMC3 autocorrplot() for any given array

The autocorrplot() function gives the autocorrelation plot for the sampled data from the trace.
If I already have a sample of data in the form of an array or list, can I use autocorrplot() to do the same?
Is there any alternative to generate autocorrelation plots given a sequence of data?
Please help.
autocorrplot is a wrapper around matplotlib's acorr. To get a similar look to pymc3's version, you can use something like
import numpy as np
import matplotlib.pyplot as plt
my_array = np.random.normal(size=1000)
plt.acorr(my_array, detrend=plt.mlab.detrend_mean, maxlags=100)
plt.xlim(0, 100)
Note the call to xlim at the end, since by default PyMC3 does not show negative correlations.

How to add interrupted time series in matplotlib

Since I am just a python beginner I hope, that I bother you not too much with my question. I'd like to plot only parts of a time series from a dataset such as this:
Code:
import numpy as np
import matplotlib.pyplot as plt
a=np.arange(10)
b=np.arange(100, 105)
c=np.arange(30, 40)
d=np.arange(55, 60)
e=np.append(a,b)
f=np.append(c,d)
plt.plot(e,f)
Plot:
Then I get a plot with a long diagonal line between the data series. What to do to get rid of that, in other words I want that the x-axis only shows 0,1,2,3,4,5,6,7,8,9,100,101,102,103,104 and the corresponding y-values and nothing in between. Moreover if I have a very long time series (e.g. from an oscilloscope measurement), is it possible to show up that some patterns are repeated with e.g. big dots in the middle of the plot? I've tried to convert the x data into a string and several other things, but it does not seem to work.
Focusing on this part of your question:
Then I get a plot with a long diagonal line between the data series. What to do to get rid of that [...]
It sounds that a scatteplot should meet your needs, so try this:
Add this to your code:
fig, ax = plt.subplots()
ax.scatter(e, f)
for i, txt in enumerate(e):
ax.annotate(txt, (e[i],f[i]))
fig.show()
To get this plot:
Unfortunately, I'm not quite sure what you're trying to accomplish with this part:
Moreover if I have a very long time series (e.g. from an oscilloscope
measurement)
Anyway, I hope my suggestion at least fixes the main part of your problem.

How to show contents of axes object when using pandas

I'm trying to wrap my head around using axes-objects in conjunction with a Pandas-dataframe (object df in the following snippet):
import matplotlib.pyplot as plt
fig=plt.figure()
axes=fig.add_subplot(111)
for key, grp in df.groupby(['bondYear', 'bondQuarter']):
axes = grp['priceAvg'].plot(label=key, ax=axes)
This runs through without any complaints, but now I'm looking for a way to actually make my plot show (and later save to *.png like with using savefig()). plt.show() works but opens two windows, one showing my plot and the other one being empty, so that's not it.
Apparently I'm missing something regarding the use of matplotlib, can you help me out?
Many thanks in advance for your help!
You shouldn't reassign your plot to axes, although that should not matter. Try this.
fig, ax = plt.subplots(figsize=(8,6))
for key, grp in df.groupby(['bondYear', 'bondQuarter']):
grp['priceAvg'].plot(label=key, ax=ax)
plt.legend()
plt.show()
plt.savefig('figname.png')
You can also plot them all at once without using iteration doing the following but you are easily able to control the legend.
fig, ax = plt.subplots(figsize=(8,6))
df.groupby(['col1', 'col2']).plot(ax=ax)

Interpolation between two xarray datasets with Basemap

I have two different xarray datasets that have different latitude/longitude grid resolutions. I want to regrid the one xarray with lower resolution to the same resolution as the one xarray with higher resolution. I found some examples (e.g., http://earthpy.org/interpolation_between_grids_with_basemap.html), but it does not work for me. Here is one example that I made for testing:
import numpy as np
import xarray as xray
import mpl_toolkits.basemap
var1=xray.DataArray(np.random.randn(len(np.linspace(40.5,49.5,10)),len(np.linspace(-39.5,-20.5,20))),coords=[np.linspace(40.5,49.5,10), np.linspace(-39.5,-20.5,20)],dims=['lat','lon'])
(xlon, xlat)=np.meshgrid(np.linspace(-39.875,-20.125,80),np.linspace(40.125,49.875,40))
var2=xray.DataArray(-xlon**2+xlat**2,coords=[np.linspace(40.125,49.875,40),np.linspace(-39.875,-20.125,80)],dims=['lat','lon'])
mpl_toolkits.basemap.interp(var1,var1.lon,var1.lat,var2.lon,var2.lat,checkbounds=False,masked=False,order=0)
I get following error:
ValueError: xout and yout must have same shape!
Screenshot:
Does basemap.interp() require xout and yout to be the same shape? So var2 needs to be a square? This is almost never the case with any of my datasets! How can I regrid var1 to be the same resolution as var2?
Note: After regridding, I want to subsample var1 given some condition related to var2. For example:
var1_subset = var1.where(var2>1000)
So I want to minimize any loss of grid points during the interpolation.
basemap.interp will work only when xout and yout are same in number or number of output nlons and nlats are same,
why not generate same length output nlats and nlons and subset it later.
For example:
import numpy as np
import xarray as xray
import mpl_toolkits.basemap
var1=xray.DataArray(np.random.randn(len(np.linspace(40.5,49.5,10)),len(np.linspace(-39.5,-20.5,20))),coords=[np.linspace(40.5,49.5,10), np.linspace(-39.5,-20.5,20)],dims=['lat','lon'])
(xlon,xlat)=np.meshgrid(np.linspace(-39.875,20.125,80),np.linspace(40.125,49.875,80))
var2=xray.DataArray(-xlon**2+xlat**2,coords[np.linspace(40.125,49.875,80),np.linspace(-39.875,-20.125,80)],dims=['lat','lon'])
mpl_toolkits.basemap.interp(var1,var1.lon,var1.lat,var2.lon,var2.lat,checkbounds=False,masked=False,order=0)
Here is another cool trick with xarray.
lonreg=var1.groupby_bins('lon',np.linspace(-39.875,20.125,80)).mean(dim='lon')
regridded=lonreg.groupby_bins('lat',np.linspace(-39.5,20.5,20)).mean(dim='lat')
if you want weighted averaged regridding, it is easy to extend this for area averaged regridding by using weights and sum function on groupby object.

Plot an IPython Notebook figure inline with fig.show()?

I'm calling the inline mode for IPython Notebook using;
%pylab inline
And the following code plots a figure immediately at the cell;
fig = plt.figure()
axes = fig.add_axes([0, 0, 1, 1])
However I would like to create the plot/axes etc. in one cell, and plot later using maybe;
fig.show()
How do I gain more control of the inline mode? If I don't use %pylab inline, it creates the plot in a seperate window which I don't want (and it usually freezes the window).
Versions;
Numpy: 1.7.0
Matplotlib: 1.2.1rc1
Python: 2.7.2 (default, Jun 24 2011, 12:22:14) [MSC v.1500 64 bit (AMD64)]
Pandas: 0.10.1
PyLab: 1.7.0
So I guess what you want is this:
from matplotlib.backends.backend_agg import FigureCanvasAgg as fc
fig = Figure()
canvas = fc(fig)
ax = fig.add_subplot(1, 1, 1)
ax.plot(arange(10))
To display the plot in another cell simply use:
fig
You might be looking for disabling autoclose figure :
InlineBackend options
---------------------
--InlineBackend.close_figures=<CBool>
Default: True
Close all figures at the end of each cell.
When True, ensures that each cell starts with no active figures, but it also
means that one must keep track of references in order to edit or redraw
figures in subsequent cells. This mode is ideal for the notebook, where
residual plots from other cells might be surprising.
When False, one must call figure() to create new figures. This means that
gcf() and getfigs() can reference figures created in other cells, and the
active figure can continue to be edited with pylab/pyplot methods that
reference the current active figure. This mode facilitates iterative editing
of figures, and behaves most consistently with other matplotlib backends,
but figure barriers between cells must be explicit.
still, IPython will show the figure if the last line of a cell return a fig object, you can avoid that by ending it with a ; or add pass as the last line.
With newer jupyter and matplotlib
Jupyter: 4.6
Jupyter notebook: 6.0
Matplotlib: 3.1
ipykernel: 5.1
all you really need is to create your figure with matplotlib.pyplot.Figure (in one cell) and then make that figure the cell value in another cell. For example
In cell [1]
%matplotlib inline
In cell [2]
from matplotlib.pyplot import Figure
from numpy import arange
from numpy.random import normal
fig = Figure()
ax = fig.add_subplot(111)
ax.plot(arange(10),normal(size=10),label='Data')
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.legend();
and finally in cell [3]
fig
That should be enough. See the screenshot below
Note suggestions with matplotlib.pyplot.ioff() and similar does not work