This question already has answers here:
How to change the font size on a matplotlib plot
(16 answers)
Closed 3 years ago.
I have a pie chart that looks like:
I tried increasing the font size using textprops={'fontsize': 18}). However, it only changes the font-size of the percentage labels inside pie, and the labels outside remain un-affected.
I want to increase fontsize of labels A, B,C etc in above pie chart.
My code:
fig1, ax1 = plt.subplots(figsize=(24,12))
flavor_pie = ax1.pie(data2.Count_Of_labels,labels=['A','B','C','D','E','F'], autopct='%.0f%%', shadow=True, colors=colors,
explode= explode1, startangle= -90, textprops={'fontsize': 18})
centre_circle = plt.Circle((0,0),0.20,fc='white')
fig = plt.gcf()
fig.gca().add_artist(centre_circle)
ax1.axis('equal')
plt.tight_layout()
plt.show()
Try:
import matplotlib as mpl
mpl.rcParams['font.size'] = 18.0
or,
mpl.rcParams.update({'font.size': 18})
or,
import matplotlib.pyplot as plt
plt.rcParams['font.size'] = 18
You might be using an older version of matplotlib; in any newer version both, the labels and autopercentages have the same size.
The question would hence boil down to how to set different font sizes for labels and autopercentages.
Having a pie chart like this
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
wedges, labels, autopct = ax.pie([1,2,3,4,3,2],labels=['A','B','C','D','E','F'],
autopct='%.0f%%', wedgeprops=dict(width=.7))
you can loop over the labels or autopercentages and set the fontsize like
for lab in labels:
lab.set_fontsize(15)
or set them all at once, like
plt.setp(labels, fontsize=15)
And similar for autopct.
Related
I have created a nested boxplot with an overlayed stripplot using the Seaborn package. I have seen answers on stackoverflow regarding how to edit box properties both for individual boxes and for all boxes using ax.artists generated by sns.boxplot.
Is there any way to edit whisker, cap, flier, etc. properties using a similar method? Currently I have to manually edit values in the restyle_boxplot method of the _BoxPlotter() class in the seaborn -> categorical.py file to get from the default plot to the desired plot:
Default Plot:
Desired Plot:
Here is my code for reference:
sns.set_style('whitegrid')
fig1, ax1 = plt.subplots()
ax1 = sns.boxplot(x="Facility", y="% Savings", hue="Analysis",
data=totalSavings)
plt.setp(ax1.artists,fill=False) # <--- Current Artist functionality
ax1 = sns.stripplot(x="Facility", y="% Savings", hue="Analysis",
data=totalSavings, jitter=.05,edgecolor = 'gray',
split=True,linewidth = 0, size = 6,alpha = .6)
ax1.tick_params(axis='both', labelsize=13)
ax1.set_xticklabels(['Test 1','Test 2','Test 3','Test 4','Test 5'], rotation=90)
ax1.set_xlabel('')
ax1.set_ylabel('Percent Savings (%)', fontsize = 14)
handles, labels = ax1.get_legend_handles_labels()
legend1 = plt.legend(handles[0:3], ['A','B','C'],bbox_to_anchor=(1.05, 1),
loc=2, borderaxespad=0.)
plt.setp(plt.gca().get_legend().get_texts(), fontsize='12')
fig1.set_size_inches(10,7)
EDIT: Note that this method appears to no longer work for matplotlib versions >=3.5. See the answer by #JohanC for an up to date answer
You need to edit the Line2D objects, which are stored in ax.lines.
Heres a script to create a boxplot (based on the example here), and then edit the lines and artists to the style in your question (i.e. no fill, all the lines and markers the same colours, etc.)
You can also fix the rectangle patches in the legend, but you need to use ax.get_legend().get_patches() for that.
I've also plotted the original boxplot on a second Axes, as a reference.
import matplotlib.pyplot as plt
import seaborn as sns
fig,(ax1,ax2) = plt.subplots(2)
sns.set_style("whitegrid")
tips = sns.load_dataset("tips")
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax1)
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax2)
for i,artist in enumerate(ax2.artists):
# Set the linecolor on the artist to the facecolor, and set the facecolor to None
col = artist.get_facecolor()
artist.set_edgecolor(col)
artist.set_facecolor('None')
# Each box has 6 associated Line2D objects (to make the whiskers, fliers, etc.)
# Loop over them here, and use the same colour as above
for j in range(i*6,i*6+6):
line = ax2.lines[j]
line.set_color(col)
line.set_mfc(col)
line.set_mec(col)
# Also fix the legend
for legpatch in ax2.get_legend().get_patches():
col = legpatch.get_facecolor()
legpatch.set_edgecolor(col)
legpatch.set_facecolor('None')
plt.show()
For matplotlib 3.5 the rectangles for the boxes aren't stored anymore in ax2.artists, but in ax2.patches. As the background of the subplot is also stored as a rectangular patch, the list of patches needs to be filtered.
The code below further makes a few adjustments:
the exact number of lines belonging to one boxplot is counted, as depending on the boxplot options there can be a different number of lines
saturation=1 is used; seaborn prefers to add some desaturation to larger areas, but lines will be better visible with full saturation
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
fig, (ax1, ax2) = plt.subplots(ncols=2, figsize=(12, 5))
sns.set_style("whitegrid")
tips = sns.load_dataset("tips")
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", ax=ax1)
sns.boxplot(x="day", y="total_bill", hue="smoker", data=tips, palette="Set1", saturation=1, ax=ax2)
box_patches = [patch for patch in ax2.patches if type(patch) == matplotlib.patches.PathPatch]
if len(box_patches) == 0: # in matplotlib older than 3.5, the boxes are stored in ax2.artists
box_patches = ax2.artists
num_patches = len(box_patches)
lines_per_boxplot = len(ax2.lines) // num_patches
for i, patch in enumerate(box_patches):
# Set the linecolor on the patch to the facecolor, and set the facecolor to None
col = patch.get_facecolor()
patch.set_edgecolor(col)
patch.set_facecolor('None')
# Each box has associated Line2D objects (to make the whiskers, fliers, etc.)
# Loop over them here, and use the same color as above
for line in ax2.lines[i * lines_per_boxplot: (i + 1) * lines_per_boxplot]:
line.set_color(col)
line.set_mfc(col) # facecolor of fliers
line.set_mec(col) # edgecolor of fliers
# Also fix the legend
for legpatch in ax2.legend_.get_patches():
col = legpatch.get_facecolor()
legpatch.set_edgecolor(col)
legpatch.set_facecolor('None')
sns.despine(left=True)
plt.show()
This question already has answers here:
Get legend as a separate picture in Matplotlib
(11 answers)
Closed 4 years ago.
I want the legend as a separate bitmap, is that possible with matplotlib?
import matplotlib
import matplotlib.pyplot as plt
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.plot([1,2,3,4,5], [1,2,3,4,5], 'r')
legend = axes.legend()
How would I save legend to bitmap? Any ideas?
If you want to have a legend in a different figure, you can use axes.get_legend_handles_labels() to get the legend handles and labels and add them to a different figure.
Also you need to provide a legend in the first plot, using the label argument, or to explicitly provide a list of labels to associate with the handles.
The following code should do what I suggested in my comment to the question:
fig = plt.figure()
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])
axes.plot([1,2,3,4,5], [1,2,3,4,5], 'r', label='test')
legend = axes.legend()
fig2 = plt.figure()
ax = fig2.add_subplot(111)
# add the legend from a different axes
ax.legend(*axes.get_legend_handles_labels())
# hide the spines and the x/y labels
ax.axis('off')
If you want more control for hiding stuff you can hide the axis spines only with
ax.set_frame_on(False)
or the x/y labels with
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
This question already has answers here:
increase the linewidth of the legend lines in matplotlib
(4 answers)
Closed 5 years ago.
What I want to do is a plot of generation and demand in an electricity grid with Matplotlib in Python. This is my code:
fig,ax = plt.subplots(figsize=(14,8))
generation.plot(kind="area", ax=ax, linewidth=1, alpha=0.9)
load.plot(kind="area", ax=ax, linewidth=1, alpha=0.9)
labels = ['Erzeugung', 'Last']
ax.legend(labels, ncol=4, loc="best", markerscale=10)
ax.set_ylabel("GW")
ax.set_xlabel("")
plt.tight_layout()
The result looks like this:
My question is about the markerscale: Why doesn't it work with this kind of plot? The problem is the bad visibility of the marker in the legend, it would be much better with a thicker line or even a box. And this without increasing the line width of the lines. Any ideas?
You can set the line size manually after creation as follows:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
fig, ax = plt.subplots(figsize=(14,8))
generation = pd.DataFrame(np.random.randint(10, 14, 10))
load = pd.DataFrame(np.random.randint(2, 5, 10))
generation.plot(kind="area", ax=ax, linewidth=1, alpha=0.9)
load.plot(kind="area", ax=ax, linewidth=1, alpha=0.9)
labels = ['Erzeugung', 'Last']
legend = ax.legend(labels, ncol=4, loc="best")
for handle in legend.legendHandles:
handle.set_linewidth(3.0)
ax.set_ylabel("GW")
ax.set_xlabel("")
plt.tight_layout()
plt.show()
Giving you something like:
I have two different sets of data with a common index, and I want to represent the first one as a barplot and the second one as a lineplot in the same graph. My current approach is similar to the following.
ax = pt.a.plot(alpha = .75, kind = 'bar')
ax2 = ax.twinx()
ax2.plot(ax.get_xticks(), pt.b.values, alpha = .75, color = 'r')
And the result is similar to this
This image is really nice and almost right. My only problem is that ax.twinx() seems to create a new canvas on top of the previous one, and the white lines are clearly seen on top of the barplot.
Is there any way to plot this without including the white lines?
You can use twinx() method along with seaborn to create a seperate y-axis, one for the lineplot and the other for the barplot. To control the style of the plot (default style of seaborn is darkgrid), you can use set_style method and specify the preferred theme. If you set style=None it resets to white background without the gridlines. You can also try whitegrid. If you want to further customize the gridlines, you can do it on the axis level using the ax2.grid(False).
import matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
matplotlib.rc_file_defaults()
ax1 = sns.set_style(style=None, rc=None )
fig, ax1 = plt.subplots(figsize=(12,6))
sns.lineplot(data = df['y_var_1'], marker='o', sort = False, ax=ax1)
ax2 = ax1.twinx()
sns.barplot(data = df, x='x_var', y='y_var_2', alpha=0.5, ax=ax2)
You have to remove grid lines of the second axis. Add to the code ax2.grid(False). However y-ticks of the second axis will be not align to y-ticks of the first y-axis, like here:
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.plot(pd.Series(np.random.uniform(0,1,size=10)), color='g')
ax2 = ax1.twinx()
ax2.plot(pd.Series(np.random.uniform(0,17,size=10)), color='r')
ax2.grid(False)
plt.show()
With the following imports:
import matplotlib as mpl
from scipy.cluster.hierarchy import dendrogram
I set the font size globally thus (based on this other Stack Overflow answer):
mpl.rcParams.update({'font.size': 20})
Then I create the dendrogram with the following (where m is a matrix created elsewhere):
dendrogram(m)
Then finally I show the plot with:
mpl.pyplot.show()
The y-axis tick labels are 20 points as expected. However, the x-axis tick labels are tiny, much smaller than 20 points. It seems like matplotlib is automatically scaling down the font size to fit the density of the data despite the font size settings above. This is the case even when I zoom in and there is plenty of room to show the larger font.
How can I make the x-axis ticks use the larger font size?
You can do it with Axes.tick_params() method:
import matplotlib as mpl
mpl.use('Agg')
import matplotlib.pyplot as plt
from scipy.cluster.hierarchy import dendrogram, linkage
import numpy
N = 20
n = numpy.random.normal(size=(N, 2))
Z = linkage(n)
# implicit interface
dendrogram(Z)
ax = plt.gca()
ax.tick_params(axis='x', which='major', labelsize=15)
ax.tick_params(axis='y', which='major', labelsize=8)
plt.savefig('t.png')
# explicit interface
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
dendrogram(Z, ax=ax)
ax.tick_params(axis='x', which='major', labelsize=15)
ax.tick_params(axis='y', which='major', labelsize=8)
fig.savefig('t.png')
Another way to adjust the x-axis font size is changing leaf_font_size:
dendrogram(linkage_matrix, leaf_font_size=8)
Here is a dendrogram tutorial that I find useful.