Seaborn/Matplotlib: how to remove the horizontal white lines that are overlaying the bars? [duplicate] - matplotlib

This question already has answers here:
how to remove grid lines on image in python?
(4 answers)
How to hide axes and gridlines in Matplotlib (python) [duplicate]
(2 answers)
How to fill legend background color when plotting with TWO axes?
(2 answers)
Closed 28 days ago.
This is how it looks:
I would like to remove the white lines that are overlaying the black bars. Btw: is it possible to remove the background behind the legend?
def stack():
data1 = [
0.7,
0.8,
0.3,
0.6,
0.5
]
data2 = [
20, 30, 23, 17, 28
]
sns.set_theme()
data = np.multiply(data1, 100)
r = [0, 1, 2, 3, 4]
fig, ax1 = plt.subplots()
ax1.bar(r, data, color="black", width=.5)
plt.ylim(0,100)
plt.ylabel('Percent')
plt.xlabel('Lineage')
ax2 = ax1.twinx()
ax2.bar(r, data2, color="red", width=.1)
plt.ylim(0,150)
plt.ylabel("Number")
lgnd1 = mpatches.Patch(color="black", label='Percent')
lgnd2 = mpatches.Patch(color="red", label='Number')
plt.legend(loc='upper center',
bbox_to_anchor=(0.5, 1.2),
ncol=3, handles=[lgnd1, lgnd2])
plt.savefig('number.svg', bbox_inches="tight", transparent=True)
plt.show()

You can use the following code :
plt.grid(False)
Or if you still want the lines you can use:
plt.grid(zorder=0)
plt.bar(range(len(y)), y, width=0.3, align='center', color='skyblue',
zorder=3)

Regarding the color of your legend: You chose this grey by setting the plot default to be the seaborn standard with sns.set_theme() (see seaborn.set_theme).
But, as described there, you are able to override every rc parameter ("runtime configuration parameter") Setting the legend background color to another color should be possible with using the parameter facecolor=... (see matplotlib.pyplot.legend, scroll down a bit )
In your case you can add this parameter here in your legend definition:
plt.legend(loc='upper center',
facecolor='white', # choose your background color
bbox_to_anchor=(0.5, 1.2),
ncol=3, handles=[lgnd1, lgnd2])

Related

Matplotlib - Change the white space between specific subplots in a grid grid

I have a grid of subplots and I would like to adjust the white space between only two of them such that the shared x labels are centred without overlapping either graph.
This question has a solution for when these are the only two subplots. However I'm struggling to adjust this to two specific subplots in a grid of many.
This code can be used to illustrate my problem.
In [1]
fig = plt.figure(figsize = (15, 10))
gs = fig.add_gridspec(2,4)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1:3])
ax3 = fig.add_subplot(gs[0, 3])
ax4 = fig.add_subplot(gs[1, 0])
ax5 = fig.add_subplot(gs[1, 1])
ax6 = fig.add_subplot(gs[1, 2])
ax7 = fig.add_subplot(gs[1, 3])
np.random.seed(19680801)
# Example data
people = ('Really Really Long Name', 'Another Long Name', 'Short Name', 'Name', 'N')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
ax5.barh(y_pos, performance, align='center')
ax5.set_yticks(y_pos, labels=people)
ax5.invert_xaxis()
ax5.set_xlabel('Label')
ax5.set_title('Bar 1')
ax6.barh(y_pos, performance, align='center')
ax6.set_yticks(y_pos, labels=people)
ax6.set_xlabel('Label')
ax6.set_title('Bar 2')
Out [1]
If I apply the solution to the linked question here then every subplot's white space is effected. I know this is because it calls on fig.dpi_scale_trans which effects the whole figure but I'm new to transforms and can't work out what to use in its place
In [2]
fig.tight_layout()
fig.subplots_adjust(wspace=0.7)
plt.setp(axes[0].yaxis.get_majorticklabels(), ha='center')
# Create offset transform by some points in x direction
dx = 60 / 72.
dy = 0 / 72.
offset = mlb.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels.
for label in ax6.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset)
Out [2]
I figured out how to solve this so posting my own answer in case anybody has a similar problem in the future.
This question and answer from 7 years ago contained the necessary help to solve the problem.
Essentially you must plot and position different GridSpecs in the figure using GridSpec from matplotlib.gridspec rather than calling one with fig.add_gridspec()
Link to GridSpec documentation
Following on from my example above I wanted to create a 2x4 grid. To do that we can plot the following grids in set positions of the figure:
Left: 1x2
Top Centre: 1x1
Bottom Centre: 2x1
Right: 1x2
In [1]:
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize = (15, 10))
# Example Data
people = ('Really Really Long Name', 'Another Long Name', 'Short Name', 'Name',
'N')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
# Left portion of grid (2x1).
# 'left' and 'right' tell the grid where it should start and finish
gs1 = GridSpec(2, 1)
gs1.update(left = 0, right = 0.2)
# Plotting empty subplots for illustration purposes
for i in gs1:
ax = plt.subplot(i)
# Mirroring on the right portion of the grid
gs2 = GridSpec(2, 1)
gs2.update(left = 0.8, right = 1)
for i in gs2:
ax = plt.subplot(i)
# Plotting in top center
# Note here we only need to plot a 1x1
gs3 = GridSpec(1, 1)
gs3.update(left = 0.25, right = 0.75, bottom = 0.53) #0.53 aligns with sides
ax3 = plt.subplot(gs3[0])
# Plotting the barh in the bottom center
# wsapce only adjusts this grid not the entire figure
gs4 = GridSpec(1, 2)
gs4.update(left = 0.2, right = 0.8, top = 0.45, wspace = 0.75)
# Left barh
ax5 = plt.subplot(gs4[0])
ax5.barh(y_pos, performance, align='center')
ax5.set_yticks([])
ax5.invert_xaxis()
ax5.set_xlabel('Label')
ax5.set_title('Bar 1')
# Right barh
ax6 = plt.subplot(gs4[1])
ax6.barh(y_pos, performance, align='center')
ax6.set_yticks(y_pos, labels=people)
ax6.set_xlabel('Label')
ax6.set_title('Bar 2')
plt.show()
Out [1]:

Problem with Removing Vertical Lines using tricontour

I am plotting zero-level contours using tricontour (do not want to have to triangulate data) and I am having trouble with getting rid of the vertical lines that occur when the y data goes to the next column of my grid and the sign of my z-value changes. I have tried using mask, nan, and removing the data points for which this occurs, with no luck.
Here is the code that I am using
plt.title(case+ r" case: $\alpha={}$ - Zero-level Contour Plots of Re$(|M(\gamma)|)$ and Im$|M(\gamma)|$".format(alp_val), fontsize = 16)
plt.tricontour(xx,yy,redett, levels=[0], colors='red')
plt.tricontour(xx,yy,imdett, levels=[0], colors = 'blue', linestyles='dashed')
plt.xlabel(r"x", fontsize=24)
plt.ylabel(r"$y$", fontsize=24)
plt.legend(custom_lines, [r"Re$(|M(\gamma)|)$", r"Im$(|M(\gamma)|)$"])
plt.scatter(0,0, s = 45, color='white', edgecolor='black', label =r'Simple Eigenvalue $\gamma=0$')
plt.scatter(zeroes,np.zeros(len(zeroes)), s = 45, color = 'green', edgecolor='black', label = r'Zero of $\mathcal{E}(\gamma)$')
plt.grid()
plt.show()
Want to remove vertical lines on this

How can I save figures in matplotlib correctly? [duplicate]

This question already has answers here:
Matplotlib (pyplot) savefig outputs blank image
(5 answers)
Closed 1 year ago.
I have been trying to save my figures using the following code, but the figure being saved in the directory is just blank. What mistake am I doing?
The code I am using is:
import matplotlib as mpl
mpl.matplotlib_fname()
musti = "/Users/Mustafa/Project RS 2/XRF.csv"
df = pd.read_csv(musti)
df
fig = plt.figure(figsize = (3,5))
plt.plot(Cl1, depth, color= "blue", linewidth=1, label='Cl1')
plt.plot(Cl2, depth, color= "green", linewidth=1, label='mean')
plt.plot(Cl3, depth, color= "red", linewidth=1, label='mean')
plt.plot(Cl4, depth, color= "brown", linewidth=1, label='mean')
plt.plot(Cl5, depth, color= "black", linewidth=1, label='mean')
plt.xlabel('Counts')
plt.ylabel('Depth')
plt.ylim(1000, 0)
plt.xlim(750, 2000)
plt.grid(True)
plt.legend(loc=4)
plt.show()
plt.savefig("C:/Users/Mustafa/Python Project/musti.png", bbox_inches="tight", dpi=300, pad_inches=2, transparent=True)
You should switch the order of the last 2 lines. If you show the plot first, it is 'consumed' and there is nothing to save.
plt.savefig("C:/Users/Mustafa/Python Project/musti.png", bbox_inches="tight", dpi=300, pad_inches=2, transparent=True)
plt.show()

How do I extend the margin at the bottom of a figure in Matplotlib?

The following screenshot shows my x-axis.
I added some labels and rotated them by 90 degrees in order to better read them. However, pyplot truncates the bottom such that I'm not able to completely read the labels.
How do I extend the bottom margin in order to see the complete labels?
Two retroactive ways:
fig, ax = plt.subplots()
# ...
fig.tight_layout()
Or
fig.subplots_adjust(bottom=0.2) # or whatever
Here's a subplots_adjust example: http://matplotlib.org/examples/pylab_examples/subplots_adjust.html
(but I prefer tight_layout)
A quick one-line solution that has worked for me is to use pyplot's auto tight_layout method directly, available in Matplotlib v1.1 onwards:
plt.tight_layout()
This can be invoked immediately before you show the plot (plt.show()), but after your manipulations on the axes (e.g. ticklabel rotations, etc).
This convenience method avoids manipulating individual figures of subplots.
Where plt is the standard pyplot from:
import matplotlib.pyplot as plt
fig.savefig('name.png', bbox_inches='tight')
works best for me, since it doesn't reduce the plot size compared to
fig.tight_layout()
Subplot-adjust did not work for me, since the whole figure would just resize with the labels still out of bounds.
A workaround I found was to keep the y-axis always a certain margin over the highest or minimum y-values:
x1,x2,y1,y2 = plt.axis()
plt.axis((x1,x2,y1 - 100 ,y2 + 100))
fig, ax = plt.subplots(tight_layout=True)
This is rather complicated, but it gives a general and neat solution.
import numpy as np
value1 = 3
xvalues = [0, 1, 2, 3, 4]
line1 = [2.0, 3.0, 2.0, 5.0, 4.0]
stdev1 = [0.1, 0.2, 0.1, 0.4, 0.3]
line2 = [1.7, 3.1, 2.5, 4.8, 4.2]
stdev2 = [0.12, 0.18, 0.12, 0.3, 0.35]
max_times = [max(line1+stdev1),max(line2+stdev2)]
min_times = [min(line1+stdev1),min(line2+stdev2)]
font_size = 25
max_total = max(max_times)
min_total = min(min_times)
max_minus_min = max_total - min_total
step_size = max_minus_min/10
head_space = (step_size*3)
plt.figure(figsize=(15, 15))
plt.errorbar(xvalues, line1, yerr=stdev1, fmt='', color='b')
plt.errorbar(xvalues, line2, yerr=stdev2, fmt='', color='r')
plt.xlabel("xvalues", fontsize=font_size)
plt.ylabel("lines 1 and 2 Test "+str(value1), fontsize=font_size)
plt.title("Let's leave space for the legend Experiment"+ str(value1), fontsize=font_size)
plt.legend(("Line1", "Line2"), loc="upper left", fontsize=font_size)
plt.tick_params(labelsize=font_size)
plt.yticks(np.arange(min_total, max_total+head_space, step=step_size) )
plt.grid()
plt.tight_layout()
Result:

How to remove padding/border in a matplotlib subplot

The second subplot is just the first image with an overlay ploted. In the second plot there appears to have white padding/boarder. How do I remove this padding/whitespace?
For completness, here is the fragment of code that performs the plotting:
fig, ax = plt.subplots(1, 2)
fig.set_size_inches(16, 6, forward=True)
plt.subplots_adjust(0.05, 0.05, 0.95, 0.95, 0.05, 0.05)
ax[0].set_title("Region Labels")
ax[0].imshow(image_labels)
ax[1].set_title("Region Connectivity Graph")
ax[1].imshow(image_labels)
for edge in edges:
ax[1].plot([centers[edge[0]][0],centers[edge[1]][0]],
[centers[edge[0]][1],centers[edge[1]][1]])
for a in ax:
a.set_xticks(())
a.set_yticks(())
plt.show()
By default, Matplotlib adds some margin to plotted data. I cant test it because it dont have your image_labels and centers, but this should normally work:
ax[1].autoscale_view('tight')
An alternative would be to manually set the xlim and ylim of the axes:
ax[1].set_xlim(0,image_labels.shape[1])
ax[1].set_ylim(0,image_labels.shape[0])