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

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')

Related

Use scientific notation for Python plots by default

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

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.

Border on errorbars in matplotlib/python

I am looking for a way to set a black border on the errorbars in my plot,
The following code:
ax.errorbar(x, y, yerr, fmt='o', label='label',color="#8da0cb",capthick=2, elinewidth=2,zorder=10)
produces:
I find it more aesthetically pleasing if there was a black border around the errorbar like there is on the marker.
Thanks for any help you can provide
Not a great solution, but you could get close by plotting the errorbars again behind your original ones, with a wider line and cap thinkness, and setting the colour of those ones to black. We can make use of the zorder kwarg to put them behind the others.
Heres a MWE:
import matplotlib.pyplot as plt
import numpy as np
# Fake data
x=np.arange(0,5,1)
y=np.ones(x.shape)
yerr = np.ones(x.shape)/4.
# Create figure
fig,ax = plt.subplots(1)
# Set some limits
ax.set_xlim(-1,5)
ax.set_ylim(-2,4)
# Plot errorbars with the line color you want
ax.errorbar(x,y,yerr, fmt='o',color='r',capthick=2,elinewidth=2,capsize=3,zorder=10)
# Plot black errorbars behind (lower zorder) with a wider line and cap thinkness
ax.errorbar(x,y,yerr, fmt='o',color='k',capthick=4,elinewidth=4,capsize=4,zorder=5)
plt.show()
Again, not a perfect solution, but at least it allows you to include it in the legend. This time, rather than plot the errorbars twice, we will use the matplotlib.patheffects module to add a Stroke to the errorbars.
errorbar returns several Line2D and LineCollection objects, so we need to apply the stroke to each of the relevant ones.
import matplotlib.patheffects as path_effects
e = ax.errorbar(x,y,yerr, fmt='o',color='r',capthick=2,elinewidth=2, label='path effects')
e[1][0].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
e[1][1].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
e[2][0].set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'),
path_effects.Normal()])
ax.legend(loc=0)
As far as I can see from the information provided in the webpage of pyplot I do not see a valid kwargs that exists for what you are asking.
There exists mfc, mec, ms and mew which are markerfacecolor, markeredgecolor, markersize and markeredgewith. It can probably be asked in GitHub so that people take this into consideration and add it in the next version of matplotlib.
Also taking a look at the answer for this question asked in Stackoverflow, I don't believe it can be done.

Changing tick label line spacing in matplotlib

I have a quite cluttered plot with y-ticklabels that need to be very long. I've resorted into wrapping them into multiline text with textwrap. However that makes the labels overlap (or at least come too close), between categories.
I can't solve it by spacing the ticks, making the graph larger, changing font or making the text smaller. (I've already pushed these limits)
As I see it, I could resolve and make it work if I could adjust the line spacing/height to be less than what the font requests.
So imagine for simplicity's sake the following tick-label desperately needs shorter line distance between lines/line height:
from matplotlib import pyplot as plt
plt.barh(0.75, 10, height=0.5)
plt.ylim(0, 2)
plt.yticks([1], ["A very long label\nbroken into 2 line"])
plt.subplots_adjust(left=0.3)
plt.show()
I've checked plt.tick_params() the rcParams without finding any obvious solution. I'm using latex to format the text, but trying to use \hspace(0.5em} in the tick label string seemed not to work/only make things worse.
Any suggestion as to how the line spacing can be decreased would be much appreciated.
You can use the linespacing keyword in your plt.yticks line. For example:
plt.yticks([1], ["A very long label\nbroken into 2 line"],linespacing=0.5)
You can play with the exact value of linespacing to fit your needs. Hope that helps.
Here's the original output of your code:
And here it is with a linespacing of 0.5:
Attempt using this:
pylab.rcParams['xtick.major.pad']='???'
Mess around with the ??? value to get something you like. You could also try (sing the OO interface):
fig = plt.figure()
ax = fig.add_subplot(111)
ax.tick_params(axis='both', which='major', labelsize=8)
ax.set_yticks([1], ["A very long label\nbroken into 2 line"], linespacing=0.5)
plt.show()
The labelsize command will change the size of your font.
Use a combination of the above with the rcparams setup.

How to adjust padding with cutoff or overlapping labels

Updated MRE with subplots
I'm not sure of the usefulness of the original question and MRE. The margin padding seems to be properly adjusted for large x and y labels.
The issue is reproducible with subplots.
Using matplotlib 3.4.2
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.show()
Original
I am plotting a dataset using matplotlib where I have an xlabel that is quite "tall" (it's a formula rendered in TeX that contains a fraction and is therefore has the height equivalent of a couple of lines of text).
In any case, the bottom of the formula is always cut off when I draw the figures. Changing figure size doesn't seem to help this, and I haven't been able to figure out how to shift the x-axis "up" to make room for the xlabel. Something like that would be a reasonable temporary solution, but what would be nice would be to have a way to make matplotlib recognize automatically that the label is cut off and resize accordingly.
Here's an example of what I mean:
import matplotlib.pyplot as plt
plt.figure()
plt.ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
plt.xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$', fontsize=50)
plt.title('Example with matplotlib 3.4.2\nMRE no longer an issue')
plt.show()
The entire ylabel is visible, however, the xlabel is cut off at the bottom.
In the case this is a machine-specific problem, I am running this on OSX 10.6.8 with matplotlib 1.0.0
Use:
import matplotlib.pyplot as plt
plt.gcf().subplots_adjust(bottom=0.15)
# alternate option without .gcf
plt.subplots_adjust(bottom=0.15)
to make room for the label, where plt.gcf() means get the current figure. plt.gca(), which gets the current Axes, can also be used.
Edit:
Since I gave the answer, matplotlib has added the plt.tight_layout() function.
See matplotlib Tutorials: Tight Layout Guide
So I suggest using it:
fig, axes = plt.subplots(ncols=2, nrows=2, figsize=(8, 6))
axes = axes.flatten()
for ax in axes:
ax.set_ylabel(r'$\ln\left(\frac{x_a-x_b}{x_a-x_c}\right)$')
ax.set_xlabel(r'$\ln\left(\frac{x_a-x_d}{x_a-x_e}\right)$')
plt.tight_layout()
plt.show()
In case you want to store it to a file, you solve it using bbox_inches="tight" argument:
plt.savefig('myfile.png', bbox_inches="tight")
An easy option is to configure matplotlib to automatically adjust the plot size. It works perfectly for me and I'm not sure why it's not activated by default.
Method 1
Set this in your matplotlibrc file
figure.autolayout : True
See here for more information on customizing the matplotlibrc file: http://matplotlib.org/users/customizing.html
Method 2
Update the rcParams during runtime like this
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})
The advantage of using this approach is that your code will produce the same graphs on differently-configured machines.
plt.autoscale() worked for me.
You can also set custom padding as defaults in your $HOME/.matplotlib/matplotlib_rc as follows. In the example below I have modified both the bottom and left out-of-the-box padding:
# The figure subplot parameters. All dimensions are a fraction of the
# figure width or height
figure.subplot.left : 0.1 #left side of the subplots of the figure
#figure.subplot.right : 0.9
figure.subplot.bottom : 0.15
...
There is also a way to do this using the OOP interface, applying tight_layout directly to a figure:
fig, ax = plt.subplots()
fig.set_tight_layout(True)
https://matplotlib.org/stable/api/figure_api.html
for some reason sharex was set to True so I turned it back to False and it worked fine.
df.plot(........,sharex=False)
You need to use sizzors to modify the axis-range:
import sizzors as sizzors_module
sizzors_module.reshape_the_axis(plt).save("literlymylief.tiff")

Categories