Use scientific notation for Python plots by default - python

Simple question: how do I get Python to use scientific notation in its plots by default? From various posts on SO I can write something like
from numpy import linspace
import matplotlib.pyplot as plt
plt.figure()
plt.plot(linspace(1e6,2e6),linspace(1e6,1e7))
plt.figure()
plt.plot(linspace(8e6,9e6),linspace(2e6,2.5e7))
plt.ticklabel_format(style='sci', axis='both', scilimits=(-2,2))
plt.show()
but ticklabel_format only acts on the last plot generated by matplotlib. (If plt.ticklabel_format() is put at the beginning of the code, I also get a blank figure showing the x,y axes.)

You can modify the default behaviour of matplotlib by edditing your "rc" file. See Customizing matplotlib.
In you case, it looks like you could adjust the item:
axes.formatter.limits : -2, 2 # use scientific notation if log10
# of the axis range is smaller than the
# first or larger than the second

Related

In a pairplot, how can I not show confidence intervals but display grid lines instead? [duplicate]

I'm plotting two data series with Pandas with seaborn imported. Ideally I would like the horizontal grid lines shared between both the left and the right y-axis, but I'm under the impression that this is hard to do.
As a compromise I would like to remove the grid lines all together. The following code however produces the horizontal gridlines for the secondary y-axis.
import pandas as pd
import numpy as np
import seaborn as sns
data = pd.DataFrame(np.cumsum(np.random.normal(size=(100,2)),axis=0),columns=['A','B'])
data.plot(secondary_y=['B'],grid=False)
You can take the Axes object out after plotting and perform .grid(False) on both axes.
# Gets the axes object out after plotting
ax = data.plot(...)
# Turns off grid on the left Axis.
ax.grid(False)
# Turns off grid on the secondary (right) Axis.
ax.right_ax.grid(False)
sns.set_style("whitegrid", {'axes.grid' : False})
Note that the style can be whichever valid one that you choose.
For a nice article on this, refer to this site.
The problem is with using the default pandas formatting (or whatever formatting you chose). Not sure how things work behind the scenes, but these parameters are trumping the formatting that you pass as in the plot function. You can see a list of them here in the mpl_style dictionary
In order to get around it, you can do this:
import pandas as pd
pd.options.display.mpl_style = 'default'
new_style = {'grid': False}
matplotlib.rc('axes', **new_style)
data = pd.DataFrame(np.cumsum(np.random.normal(size=(100,2)),axis=0),columns=['A','B'])
data.plot(secondary_y=['B'])
This feels like buggy behavior in Pandas, with not all of the keyword arguments getting passed to both Axes. But if you want to have the grid off by default in seaborn, you just need to call sns.set_style("dark"). You can also use sns.axes_style in a with statement if you only want to change the default for one figure.
You can just set:
sns.set_style("ticks")
It goes back to normal.

Cannot remove connecting lines from scatterplot using plt.plot()

I am trying to produce a scatterplot WITHOUT lines connecting each marker using matplotlib.pyplot.plot(). I am using Python 2.
I have tried setting specifying in the plt.plot() function that linestyle='None'. I have also tried linestyle='' (this has no impact on the line) and linestyle=None (this raises an error). I have also tried setting the line width to 0, and I have tried altering the linestyle to a different type of dash. Neither worked.. the code ran without an error message and the connecting lines remained without alteration.
#!/usr/bin/env python
import matplotlib.pyplot as plt
import numpy as np
x=[0,1,2,3]
y=[2,4,6,8]
yError=[0.1,0.2,0.2,0.3]
fig = plt.figure(facecolor="w",figsize=(6.5,4.0))
ax = fig.add_subplot(111)
ax.plot(x, y, color='blue',marker='o',label='generic', linestyle='None')
ax.errorbar(x,y, yerr=yError, color='blue',label='_nolegend_')
plt.show()
The output I am hoping for is a scatterplot without connecteing lines.
The lines are plot by your errorplot.
Add there also the linestyle='None' kwarg, then they'll disappear.
You can even leave away the complete plot command when also adding the marker definition to errorplot.
Then you only should adapt also the label of course.
The shortest and best readable form imo would rather be using the format kwarg to specify color, marker and no line in one short term:
ax.errorbar(x,y, fmt='bo', yerr=yError, label='generic')

Chevron linestyle in matplotlib

Is it possible to make a dashed linestyle using more complicated shapes in matplotlib (or any other python plotting library)? It's easy to make a linestyle with different spacings and combinations of dots and dashes, but I'm after something like this:
I can envision a way of doing it by writing a function from scratch to take a custom chevron marker style and working out the angle to display it at and the correct spacing etc. However that seems like an overly complicated way to address the problem that will easily break down for things like different specified line widths.
If you find a better latex symbol, you could do something like this.
import numpy as np
import matplotlib
matplotlib.rc('text', usetex=True)
matplotlib.rcParams['text.latex.preamble'] = [r'\boldmath', r'\usepackage{amsmath}', r'\usepackage{amssymb}', r'\usepackage{fontawesome}']
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot('111')
ax.plot(np.linspace(0,10,10),np.repeat(10,10),marker='$>$',ls='',ms=50,mew=10)
plt.show()
Look at the symbols in the fontawesome latex package, it might have something closer to what you're wanting. Then you can substitute the marker marker='$>$' for another latex symbol.

Using a colormap for matplotlib line plots

I’d like to employ the reverse Spectral colormap ,
https://matplotlib.org/examples/color/colormaps_reference.html
for a lineplot.
This works fine with a hex bin plot::
color_map = plt.cm.Spectral_r
image = plt.hexbin(x,y,cmap=color_map)
but when I do
ax1.plot(x,y, cmp=color_map)
this gives me::
AttributeError: Unknown property cmap
Note, I just want to set the colormap and let matplotliob do the rest; i.e. I don't want to have a color=' argument in the .plot command.
You can have a look at this solution - the third variant is what you want:
https://stackoverflow.com/a/57227821/5972778
You need to know how many lines you're plotting in advance, as otherwise it doesn't know how to choose the colours from the range.
I think that seaborn's color_palette function is very convenient for this purpose. It can be used in a with statement to temporarily set the color cycle for a plot or set of plots.
For example:
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
with sns.color_palette("Spectral", n_colors=10):
plt.plot(np.random.rand(5, 10))
You can use with any predefined matplotlib or seaborn colormap, or provide a custom sequence of colors.

Why do matplotlib subplots start with 1

When creating subplots with matplotlib you need to start with 1, while most other python things start with zero. So to create the very first subplot (top left)
ax = fig.add_subplot(3,4,1)
Where I would have expected 0 to be the first subplot
ax = fig.add_subplot(3,4,0)
I've seen the explanation "we got this from matlab" but that seems like a particularly unsatisfying answer.
The answer really is: "it's meant for matlab-compatibility". There is one minor advantage in terms of the shortcut integer notation (subplot(231) instead of subplot(2,3,1)). You can't express a 0-based system that way without using strings instead. However, that shortcut notation is generally a bad idea, and should only ever be used in an interactive scenario where readability isn't a concern.
As #Cong Ma mentioned, in most cases, you'd use subplots and index a 2D array instead of the matlab-style numerical system. It's a better approach all-around.
For example:
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=2, ncols=3)
axes[0, 0].plot(range(10))
plt.show()
It's not exactly identical, as it also adds all of the subplots, but you can always hide the ones you don't want to be visible (ax.axis('off') or ax.set(visible=False)).

Categories