legend setting (numpoints and scatterpoints) in matplotlib does not work - python

I tried to get the legend right for the dashed line so I played with the rcParams a little bit, but it for some reasons wouldn't work on my computer.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['legend.numpoints'] = 5
matplotlib.rcParams['legend.scatterpoints'] = 5
fig, axs = plt.subplots()
axs.plot(range(10), '--k', label="line")
axs.plot(range(10), range(10)[::-1], ':k', label="scatter")
axs.legend(loc=9)
plt.show()
And the resultant figure is:
And as can be seen, the numpoints for the dashed line is not enough. Would anyone please help?
Thanks!

If you make a plot with markers, matplotlib.rcParams['legend.numpoints'] adjust the number of points drawn on the legend lines.
If you substitute your plot by these:
axs.plot(range(10), '--k', label="line", marker='d')
axs.plot(range(10), range(10)[::-1], ':k', label="scatter", marker='o')
you get this image:
I don't know what does matplotlib.rcParams['legend.scatterpoints'] do, but I guess regulates the number of points in the legend of scatter plots.
If you want to change the length of the lines in the legend give a try with matplotlib.rcParams['legend.handlelength'] and/or matplotlib.rcParams['legend.handleheight']. More info about rc file can be found here
As suggested by #tcaswell, you don't have to set rc parameters. All the legend.* parameters are available as keywords for the legend function. See matplotlib.pyplot.legend documentation

Related

How to add a marker in a specific point in a seaborn lineplot?

I'm plotting a simple lineplot with seaborn and I'd like to add a marker in two specific points of the lineplot.
I checked the documentation, and I know that matplotlib has some markers support (https://matplotlib.org/3.1.0/api/markers_api.html), but I couldn't find a solution for my problem.
I have something like this:
sns.lineplot(x="time", y="cost",
data=df_time)
I'd want to specify the plot to have a marker at both the rows n1 and n2. Is that possible?
The show a marker of the first and second point of a line plot use the markevery argument.
import matplotlib.pyplot as plt
x = [1,3,4,6,7,9]
y = [3,2,3,1,3,2]
plt.plot(x,y, marker="s", ms=12, markevery=[0,1])
plt.show()

Using markevery kwarg with axhline

I was trying to plot a vertical line with markers on it using ax.axvline but the markers only show up on the bottom and top of the figure. I have played around with the markevery kwarg but it does not seem to have any effect when I change it even though it works for a normal line plot. Does anyone know if this is because no discrete values are specified along the axis or am I just doing something wrong?
I realize that I can plot a vertical line on my own and specify the markers, but I figure given the purpose of axvline I should use it.
Here is an example code of what I am talking about:
import matplotlib.pyplot as plt
import numpy as np
x = np.arange(-10,10)
y = x**2-15.
fig = plt.figure(figsize=(4,4))
ax = plt.subplot(111)
ax.plot(y,x) #Test curve
ax.plot(2+np.zeros(len(x)),x,marker='X',markevery=1) #another way to plot what I want.
ax.axvline(0,c='r',marker='X',markevery=1) #markerevery doesn't seem to work
plt.show()
As mentioned by ImportanceofBeingErnest, the markereverykwarg does not apply for axvline or axhline because there are technically only 2 points used to draw the line at the boundaries.

Matplotlib ylim and xlim not working in combination of scatter plot and line plot or fill_between

I encounter a plotting issue I don't understand. Below code shall draw a straight line, fill the area above the line with a colour and plot several scattered dots in it. That all works but if I combine scatter and any of line or fill_between I cannot set the plot limits. The plot area is much larger than it had to be.
So how do I set the plot limits?
from matplotlib import pyplot as plt
import numpy as np
x = np.linspace(0,160,100)
MCSample = np.random.normal(112,10,1000)
YSample = np.random.normal(100,2.41,1000)
y_limit = max(160, np.max(YSample))
fig, ax = plt.subplots(1, 1)
ax.plot(x,x, label="Limit State function")
ax.scatter(MCSample,YSample, marker='.', color='b', alpha=0.5)
ax.fill_between(x,y_limit,x, alpha=0.1, color='r')
ax.set_xlim=(0,160)
ax.set_ylim=(0,y_limit)
plt.show()
I'm using Python 3.5.1 and Matplotlib 1.5.1.
In your code you are setting ax.set_xlim to equal (0,160).
All you have to do to make your code work is to get rid of the equal signs as shown below:
ax.set_xlim(0,160)
ax.set_ylim(0,y_limit) # no equals sign on these 2 lines
Now you are applying those limits to the graph rather than defining them to equal the limits.

How to use seaborn pointplot and violinplot in the same figure? (change xticks and marker of pointplot)

I am trying to create violinplots that shows confidence intervals for the mean. I thought an easy way to do this would be to plot a pointplot on top of the violinplot, but this is not working since they seem to be using different indices for the xaxis as in this example:
import matplotlib.pyplot as plt
import seaborn as sns
titanic = sns.load_dataset("titanic")
titanic.dropna(inplace=True)
fig, (ax1,ax2,ax3) = plt.subplots(1,3, sharey=True, figsize=(12,4))
#ax1
sns.pointplot("who", "age", data=titanic, join=False,n_boot=10, ax=ax1)
#ax2
sns.violinplot(titanic.age, groupby=titanic.who, ax=ax2)
#ax3
sns.pointplot("who", "age", data=titanic, join=False, n_boot=10, ax=ax3)
sns.violinplot(titanic.age, groupby=titanic.who, ax=ax3)
ax3.set_xlim([-0.5,4])
print(ax1.get_xticks(), ax2.get_xticks())
gives: [0 1 2] [1 2 3]
Why are these plots not assigning the same xtick numbers to the 'who'-variable and is there any way I can change this?
I also wonder if there is anyway I can change the marker for pointplot, because as you can see in the figure, the point is so big so that it covers the entire confidence interval. I would like just a horizontal line if possible.
I'm posting my final solution here. The reason I wanted to do this kind of plot to begin with, was to display information about the distribution shape, shift in means, and outliers in the same figure. With mwaskom's pointers and some other tweaks I finally got what I was looking for.
The left hand figure is there as a comparison with all data points plotted as lines and the right hand one is my final figure. The thick grey line in the middle of the violin is the bootstrapped 99% confidence interval of the mean, which is the white horizontal line, both from pointplot. The three dotted lines are the standard 25th, 50th and 75th percentile and the lines outside that are the caps of the whiskers of a boxplot I plotted on top of the violin plot. Individual data points are plotted as lines beyond this points since my data usually has a few extreme ones that I need to remove manually like the two points in the violin below.
For now, I am going to to continue making histograms and boxplots in addition to these enhanced violins, but I hope to find that all the information is accurately captured in the violinplot and that I can start and rely on it as my main initial data exploration plot. Here is the final code to produce the plots in case someone else finds them useful (or finds something that can be improved). Lots of tweaking to the boxplot.
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
#change the linewidth which to get a thicker confidence interval line
mpl.rc("lines", linewidth=3)
df = sns.load_dataset("titanic")
df.dropna(inplace=True)
x = 'who'
y = 'age'
fig, (ax1,ax2) = plt.subplots(1,2, sharey=True, figsize=(12,6))
#Left hand plot
sns.violinplot(df[y], groupby=df[x], ax=ax1, inner='stick')
#Right hand plot
sns.violinplot(df[y], groupby=df[x], ax=ax2, positions=0)
sns.pointplot(df[x],df[y], join=False, ci=99, n_boot=1000, ax=ax2, color=[0.3,0.3,0.3], markers=' ')
df.boxplot(y, by=x, sym='_', ax=ax2, showbox=False, showmeans=True, whiskerprops={'linewidth':0},
medianprops={'linewidth':0}, flierprops={'markeredgecolor':'k', 'markeredgewidth':1},
meanprops={'marker':'_', 'color':'w', 'markersize':6, 'markeredgewidth':1.5},
capprops={'linewidth':1, 'color':[0.3,0.3,0.3]}, positions=[0,1,2])
#One could argue that this is not beautiful
labels = [item.get_text() + '\nn=' + str(df.groupby(x).size().loc[item.get_text()]) for item in ax2.get_xticklabels()]
ax2.set_xticklabels(labels)
#Clean up
fig.suptitle('')
ax2.set_title('')
fig.set_facecolor('w')
Edit: Added 'n='
violinplot takes a positions argument that you can use to put the violins somewhere else (they currently just inherit the default matplotlib boxplot positions).
pointplot takes a markers argument that you can use to change how the point estimate is rendered.

matplotlib scatter plot change distance in x-axis

I want to plot some Data with Matplotlib scatter plot.
I used the following code to plot the Data as a scatter with using the same axes for the different subplots.
import numpy as np
import matplotlib.pyplot as plt
epsilon= np.array([1,2,3,4,5])
f, (ax1, ax2, ax3, ax4) = plt.subplots(4, sharex= True, sharey=True)
ax1.scatter(epsilon, mean_percent_100_0, color='r', label='Totaldehnung= 0.000')
ax1.scatter(epsilon, mean_percent_100_03, color='g',label='Totaldehnung= 0.003')
ax1.scatter(epsilon, mean_percent_100_05, color='b',label='Totaldehnung= 0.005')
ax1.set_title('TOR_R')
ax2.scatter(epsilon, mean_percent_111_0,color='r')
ax2.scatter(epsilon, mean_percent_111_03,color='g')
ax2.scatter(epsilon, mean_percent_111_05,color='b')
ax3.scatter(epsilon, mean_percent_110_0,color='r')
ax3.scatter(epsilon, mean_percent_110_03,color='g')
ax3.scatter(epsilon, mean_percent_110_05,color='b')
ax4.scatter(epsilon, mean_percent_234_0,color='r')
ax4.scatter(epsilon, mean_percent_234_03,color='g')
ax4.scatter(epsilon, mean_percent_234_05,color='b')
# Fine-tune figure; make subplots close to each other and hide x ticks for
# all but bottom plot.
f.subplots_adjust(hspace=0.13)
plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
plt.locator_params(axis = 'y', nbins = 4)
ax1.grid()
ax2.grid()
ax3.grid()
ax4.grid()
plt.show()
Now i want to have a x-axis with smaller space between each point. I tried to change the range but it was not working. Can someone help me?
To make the x ticks come closer you might have to set the dimensions of the figure.
Since, in your case, the figure is already created, Set the size of the plot using set_size_inches method of the figure object.
This question contains a few other ways to do the same.
Adding the following line before the plt.show()
fig.set_size_inches(2,8)
Gives me this :
Which I hope is what you are trying to do.

Categories