I have a plot of a map containing areas which are color coded. I need to remove the automatic color bar from the plot and replace with a legend. However, I cannot find a way to remove the color bar. Xarray was used to create the data array.
map_crs = ccrs.OSGB()
fig = plt.figure(figsize=(10, 15))
cmap = mpl.colors.ListedColormap(colours)
norm = mpl.colors.BoundaryNorm(boundaries=bins, ncolors=len(cmap.colors)-1 )
stamen_terrain = cigmt.Stamen('terrain')
ax = plt.axes(projection=stamen_terrain.crs)
data_array.plot(transform=map_crs, vmin=0, vmax=np.max(data_array), cmap=cmap)
plt.gca().coastlines()
plt.tight_layout()
plt.savefig(plotname, bbox_inches="tight", pad_inches=0.1)
plt.clf()
I have tried adding commands such as, colorbar=False, cbar=False, Colorbar=False. However, just continually receive the corresponding error;
AttributeError: 'QuadMesh' object has no property 'Colorbar'
Any ideas on how to get rid of the colorbar?
Done!
Just needed to put add_colorbar=False into the plotting command.
Now to add the legend!
Related
I have a list of dataframes named merged_dfs that I am looping through to get the correlation and plot subplots of heatmap correlation matrix using seaborn.
I want to customize the colorbar tick labels, but I am having trouble figuring out how to do it with my example.
Currently, my colorbar scale values from top to bottom are
[1,0.5,0,-0.5,-1]
I want to keep these values, but change the tick labels to be
[1,0.5,0,0.5,1]
for my diverging color bar.
Here is the code and my attempt:
fig, ax = plt.subplots(nrows=6, ncols=2, figsize=(20,20))
for i, (title,merging) in enumerate (zip(new_name_data,merged_dfs)):
graph = merging.corr()
colormap = sns.diverging_palette(250, 250, as_cmap=True)
a = sns.heatmap(graph.abs(), cmap=colormap, vmin=-1,vmax=1,center=0,annot = graph, ax=ax.flat[i])
cbar = fig.colorbar(a)
cbar.set_ticklabels(["1","0.5","0","0.5","1"])
fig.delaxes(ax[5,1])
plt.show()
plt.close()
I keep getting this error:
AttributeError: 'AxesSubplot' object has no attribute 'get_array'
Several things are going wrong:
fig.colorbar(...) would create a new colorbar, by default appended to the last subplot that was created.
sns.heatmap returns an ax (indicates a subplot). This is very different to matplotlib functions, e.g. plt.imshow(), which would return the graphical element that was plotted.
You can suppress the heatmap's colorbar (cbar=False), and then create it newly with the parameters you want.
fig.colorbar(...) needs a parameter ax=... when the figure contains more than one subplot.
Instead of creating a new colorbar, you can add the colorbar parameters to sns.heatmap via cbar_kws=.... The colorbar itself can be found via ax.collections[0].colobar. (ax.collections[0] is where matplotlib stored the graphical object that contains the heatmap.)
Using an index is strongly discouraged when working with Python. It's usually more readable, easier to maintain and less error-prone to include everything into the zip command.
As now your vmin now is -1, taking the absolute value for the coloring seems to be a mistake.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
merged_dfs = [pd.DataFrame(data=np.random.rand(5, 7), columns=[*'ABCDEFG']) for _ in range(5)]
new_name_data = [f'Dataset {i + 1}' for i in range(len(merged_dfs))]
fig, axes = plt.subplots(nrows=2, ncols=3, figsize=(12, 7))
for title, merging, ax in zip(new_name_data, merged_dfs, axes.flat):
graph = merging.corr()
colormap = sns.diverging_palette(250, 250, as_cmap=True)
sns.heatmap(graph, cmap=colormap, vmin=-1, vmax=1, center=0, annot=True, ax=ax, cbar_kws={'ticks': ticks})
ax.collections[0].colorbar.set_ticklabels([abs(t) for t in ticks])
fig.delaxes(axes.flat[-1])
fig.tight_layout()
plt.show()
I have a visualization code like:
for cluster in ready_couples_2.cluster.unique():
sns.set(rc={'figure.figsize':(11.7,8.27)})
# mask the cluster of interest
is_cluster = ready_couples_2.cluster.eq(cluster)
ax = ready_couples_2[~is_cluster].plot.scatter(x='longitude',y='latitude', c='gray')
ax = sns.scatterplot(data=ready_couples_2[is_cluster],
x='longitude',
y='latitude',
hue='id_easy',
ax=ax)
ax.legend_.remove()
figure = ax.get_figure()
figure.savefig('test.png', dpi=500)
plt.show()
But figure is saving only one plot out of given plots. How to save them all OR how to define DPI while plotting?
Well, it does save all of your figures, but because you don't change the file name the last plot will be the only one you see.
You can for example do
for ind, cluster in enumerate(ready_couples_2.cluster.unique()):
...
figure.savefig('test%d.png' % ind, dpi=500)
I am trying to change location of plot legend. Below what I've got for now.
var_list=powiaty_cols[powiaty_cols.str.contains("apart_bel_40")]
for var in var_list:
fig = plt.figure(figsize=(25, 25))
ax = plt.gca()
powiaty.plot(column=var,cmap='Reds', categorical=True,
legend=True, ax=ax,edgecolor='black')
ax.legend(loc='best')
This code is plotting figure but without legend. I've received errors as follows:
No handles with labels found to put in legend.
No handles with labels found to put in legend.
No handles with labels found to put in legend.
No handles with labels found to put in legend.
But without part 'ax.legend(loc='best')' I can get my plot but legend is in upper left corner. Plotted column is filled with integer from 1 to 5. Similar issue is when I'm trying to change size of legend.
Could maybe somebody help in this?
I don't know what powiaty is, but my guess is that you need to get the Axes object back so you can continue modifying it. Try:
ax = powiaty.plot(column=var, cmap='Reds', categorical=True,
legend=True, ax=ax, edgecolor='black'
)
For me worked:
leg = ax.get_legend()
leg.set_bbox_to_anchor((0., 0.1, 0.2, 0.2))
If i run this code in python:
titles = ctf01[0,1:]
fig = plt.figure(figsize=(11.69,8.27), dpi=100)
for num in range(len(titles)):
ax = fig.add_subplot(3,4,num+1)
ax.plot(ctf03[1:,num+1], ctf0102[:,num], 'ro')
ax.set_title(titles[num])
plt.tight_layout()
fig.text(0.5, 0.04, 'CTF12', ha='center')
fig.text(0.04, 0.5, 'CTF3', va='center', rotation='vertical')
fig.savefig("example.pdf")
i get this in the pdf file:
I would like to fix the problem with the "figure title" shown in the red circles.
If i set the 0.04 value as an negative value the title runs out of paper.
I also would like to save some space with moving the title of the subplots (green circles) into the diagram. Any idea how i can realize this?
Thanks for help.
try to add before fig.savefig("example.pdf") following line.
plt.tight_layout()
you have it in your script but it should come after text
It looks like you're trying to set the x and y labels for the whole figure, which isn't possible as these can only be set on an Axes object. Fortunately we can work around it by creating an 'invisible' subplot that fills the whole area and set the labels on this.
After plotting your subplots you would create the invisible one with:
label_ax = fig.add_subplot(111, frameon=False)
The frameon argument prevents it from drawing the box that is added by the default style. Then you tell it not to draw tick marks and make the tick labels invisible (we can't just remove them as it will mess up the spacing).
label_ax.tick_params(bottom=False, left=False, labelcolor="none")
Finally, set your labels:
label_ax.set_xlabel("CTF12")
label_ax.set_ylabel("CTF3")
You can adjust the vertical positioning of the plot titles by providing a pad argument to the set_title function. Giving a negative value will push the title into the plot, you'll need trial and error to find the value that works.
Putting it all together (with made-up data):
fig = plt.figure(figsize=(11.69, 8.27), dpi=100)
for i in range(10):
ax = fig.add_subplot(3, 4, i + 1)
ax.plot([1, 2, 3, 4, 5], "ro")
ax.set_title("Plot {}".format(i), pad=-15)
label_ax = fig.add_subplot(111, frameon=False)
label_ax.tick_params(bottom=False, left=False, labelcolor="none")
label_ax.grid(False) # In case the current style displays a grid.
label_ax.set_xlabel("CTF12")
label_ax.set_ylabel("CTF3")
fig.tight_layout()
fig.savefig("example.pdf")
Which gives:
I am using matploitlib boxplot to create a figure like the following:
Using this code:
# Create a figure instance
fig = plt.figure(1, figsize=(4, 4))
# Create an axes instance
ax = fig.add_subplot(111)
ax.set_ylim([0, 1.2])
# Create the boxplot
bp = ax.boxplot(data_to_plot,widths=(0.5, 0.5))
plt.setp(bp['boxes'], linewidth=1)
# Save the figure
plt.xticks([1, 2], ['A', 'B'],fontsize=16)
plt.yticks(fontsize=16)
#fig.savefig('fig1.png', bbox_inches='tight')
plt.show()
What I am trying to get at is to set background for each box so they have different colors.
Thanks
This is only partly doing what you want, but maybe it helps you out to find the answer to your problem. You can use
bp = ax.boxplot(data_to_plot,widths=(0.5, 0.5),notch=True, patch_artist=True)
to fill the plot. In order to change the color take a look at this Example.
I ended up adding the following argument to boxplot:
bp = ax.boxplot(data_to_plot,widths=(0.5, 0.5),patch_artist=True)
and assign each box a unique color using:
bp['boxes'][0].set( facecolor = '#1b9e77' )