Matplotlib center alignment for pie chart labels - python

I have produced a very simple pie chart in Python using Matplotlib and I am wanting to edit the alignment of my labels. I have used \n within my labels to split the line as the labels are too long for one line. But as you can see from the picture called 'pie chart image', it's a mix of weird alignments at the moment. I would really like to have it center alignment.
For other chart/graph types in Matplotlib there is an argument called align where you can set it to center, however, plt.pie(...) does not seem to have this attribute.
Here is my code:
import matplotlib.pyplot as plt
k = [7,15]
labels = 'Strongly and Mostly \n Agree', 'Strongly/Mostly Disagree \n and In the Middle'
plt.pie(k, labels= labels)
plt.show()
Any ideas?

You can pass a dictionary of text properties to plt.pie via the textprops argument. For example:
plt.pie(k, labels=labels, textprops={'weight': 'bold'})
However, if you try to specify the horizontalalignment property, you'll get an error saying that you provided that parameter twice. Obviously you didn't, but matplotlib passed both it's hard-coded value and your value to some internal function.
But that's probably a good thing. The way I see it, there's not so much a mix of alignments, but a consistent alignment of the text against the pie.
Back to your question
pie returns both the patches and the labels for each wedge. So you can loop through the labels after your initial call to pie to modify their alignment. That looks like this:
k = [7, 15]
labels = 'Strongly and Mostly\nAgree', 'Strongly/Mostly Disagree\nand In the Middle'
fig, ax = plt.subplots()
ax.set_aspect('equal')
wedges, labels = ax.pie(k, labels=labels, textprops={'weight': 'bold'})
for label in labels:
label.set_horizontalalignment('center')
As you can see, the labels now overlap with the wedges, diminishing legibility.
The labels also have a set_position method (i.e., label.set_position((x, y))), but recomputing the positions for N labels in a pie chart sounds like a Bad Time to me.

Related

How can I use alpha with seaborn.pointplot? [duplicate]

I want to make a seaborn pointplot that has transparency so that I can clearly see the points located behind others of a different color.
I tried adding "alpha=0.3" to the call to pointplot and also tried the same within a catplot with kind='point'; however, neither of these results in the desired transparency (no error message is produced either).
sns.pointplot(x='aamm', y='posrate', hue='AA:XX', hue_order=[1,0], data=data, dodge=True, palette=palette, alpha=0.3)
I was hoping to get a plot with transparent points, but instead, I got one with normal opaque points. The dodge option doesn't seem to produce any noticeable effect either, in terms of separating overlapping points of different color.
Is there a way to add transparency to a seaborn pointplot or use something else to get a similar effect?
Thank you.
To the extent of my knowledge there is no more an alpha parameter that can be directly set in seaborn.
You can do the following thou:
Sample dataframe
df = pd.DataFrame(np.random.randint(low=0, high=1000, size=(50, 5)))
Plotting
ax = sns.pointplot(x=0, y=1, data=df, dodge=True,plot_kws=dict(alpha=0.3))
plt.setp(ax.collections, alpha=.3) #for the markers
plt.setp(ax.lines, alpha=.3) #for the lines

How to change axis values to italic format (Python, Matplotlib)

Currently I'm working on a university bioinformatics project. I have plot with an axis where values should be in italic format (Proteobacteria, Bacteroidata, etc should be in italic), but I can't find any solution how to change format ONLY for one axis values. I have found that using plt.rcParams.update() function can help, but it changes all plot/graph to italic format, but as I said I only need to change only one axis.
My code:
color_map = ['#dfdfdf' for i in range(len(order_count))]
color_map[0] = '#e81518'
fig, ax = plt.subplots(1,1, figsize=(13,7))
ax.barh(phyl_count['Phylum'], phyl_count['Phyl_Perc'], linewidth=0.6, color = color_map)
plt.gca().invert_yaxis()
ax.grid(axis='x', alpha=0.4)
plt.xlabel('Percent')
plt.ylabel('Phylum')
for index,data in enumerate(phyl_count['Phyl_Perc']):
plt.text(x=data+0.1, y=index+0.20,s=f'{data}%')
plt.show()
And I get this graph, how can I change Proteobacteria, Bacteriodata, etc to italic?
You can obtain a list of the labels by writing
labels = ax.get_yticklabels()
This gives you a list of the labels, where each label is an instance of Matplotlibs Text. This has a set_style-method, where one of the options is to set the text 'italic' so you can do
for lbl in labels:
lbl.set_style('italic')

Seaborn PairPlot rotate x tick labels. Categorical data labels are overlapping

I'm trying to create plots which show the correlation of the "value" parameter to different categorical parameters. Here's what I have so far:
plot = sns.pairplot(df, x_vars=['country', 'tier_code', 'industry', 'company_size', 'region'], y_vars=['value'], height=10)
Which produces the following set of plots:
As you can see, the x axis is extremely crowded for the "country" and "industry" plots. I would like to rotate the category labels 90 degrees so that they wouldn't overlap.
All the examples for rotating I could find were for other kinds of plots and didn't work for the pairplot. I could probably get it to work if I made each plot separately using catplot, but I would like to make them all at once. Is that possible?
I am using Google Colab in case it makes any difference. My seaborn version number is 0.10.0.
Manish's answer uses the get_xticklabels method, which doesn't always play well with the higher level seaborn functions in my experience. So here's a solution avoiding that. Since I don't have your data, I'm using seaborn's tips dataset for an example.
I'm naming the object returned by sns.pairplot() grid, just to remind us that it is a PairGrid instance. In general, its axes attribute yields a two-dimensional array of axes objects, corresponding to the subplot grid. So I'm using the flat method to turn this into a one-dimensional array, although it wouldn't be necessary in your special case with only one row of subplots.
In my example I don't want to rotate the labels for the third subplot, as they are single digits, so I slice the axes array accordingly with [:2].
import seaborn as sns
sns.set()
tips = sns.load_dataset("tips")
grid = sns.pairplot(tips, x_vars=['sex', 'day', 'size'], y_vars=['tip'])
for ax in grid.axes.flat[:2]:
ax.tick_params(axis='x', labelrotation=90)
You can rotate x-axis labels as:
plot = sns.pairplot(df, x_vars=['country', 'tier_code', 'industry', 'company_size', 'region'],
y_vars=['value'], height=10)
rotation = 90
for axis in plot.fig.axes: # get all the axis
axis.set_xticklabels(axis.get_xticklabels(), rotation = rotation)
plot.fig.show()
Hope it helps.

Plotting a legend with matplotlib: error

I am trying to add a legend to my graph in matplotlib. instead of creating a legend it puts the full list of all mylabels in the legend.
My graph looks like this:
The legend is cut off and i cant see more than that, i assume due to its size.
This is my code:
features2 = ["Number of Sides"]
features3 = ["Largest Angle"]
header2 = ["Label"]
data_df = pd.DataFrame.from_csv("AllMixedShapes2.csv")
X1 = np.array(data_df[features2].values)
y1 = np.array(data_df[features3].values)
l = np.array(data_df[header2].values)
plt.scatter(X1[:, 0],y1, c=y, cmap=plt.cm.Paired, label=l)
plt.axis([0, 17, 0, 200])
plt.ylabel("Maximum Angle (Degrees)")
plt.xlabel("Number Of Sides")
plt.title('Original 450 Test Shapes')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.show()
And AllMixedShapes2.csv looks like this:
I'm quite new to python and machine learning and ive tried other examples but i cant get anything to work.
Matplotlib's label argument is meant to be a single string that labels the entire dataset, rather than an array of individual labels for the points within the dataset. If you wish to pass an array of point-by-point labels that will be aggregated into a legend, the best option is probably the Seaborn library. Seaborn provides a wrapper around matplotlib for more convenient statistical visualization.
This should do approximately what you wish to do with your data:
import seaborn
seaborn.lmplot('Number of Sides', 'Largest Angle', hue='Label',
data=data_df, fit_reg=False)
I'd suggest checking out the seaborn example gallery for more ideas.

Seaborn Boxplot: get the xtick labels

I am using Seaborn to make a boxplot using data from a pandas dataframe.
colorpalette = sns.hls_palette(8,h=.9)
g = sns.boxplot(x="estimator", y="mean_score", data=dFrame, palette=colorpalette)
g.set(ylabel='Mean Accuracy', xlabel='')
plt.show()
This results me in the previous figure. As you can see the ticklabels are too long to be in one line. So, I plan to use textwrap on the xticklabels to span them over multiple rows. In order to get the labels, I tried using
g.xaxis.get_ticklabels()
Returns me the following
<a list of 9 Text major ticklabel objects>
If I try it in a loop like this
for item in g.xaxis.get_ticklabels():
print(item)
I get the following output
Text(0,0,'ExtraTreesClassifier')
Text(1,0,'RandomForestClassifier')
Text(2,0,'GradientBoostingClassifier')
Text(3,0,'LogisticRegression')
Text(4,0,'DecisionTreeClassifier')
Text(5,0,'kNearestNeighbors')
Text(6,0,'LinearSVC')
Text(7,0,'Perceptron')
Is there a way to do it more efficiently using default functions/methods in seaborn.
Having a matplotlib axes instance ax (as it is e.g. returned by seaborn plots),
ax = sns.boxplot(...)
allows to obtain the ticklabels as
ax.get_xticklabels()
The easiest way to get the texts out of the list would be
texts = [t.get_text() for t in ax.get_xticklabels()]
Wrapping the text could be done as well on the fly
texts = [textwrap.fill(t.get_text(), 10) for t in ax.get_xticklabels()]
and even setting the text back as ticklabels can be done in the same line
ax.set_xticklabels([textwrap.fill(t.get_text(), 10) for t in ax.get_xticklabels()])
The accepted answer didn't work for me (there was message like: 'FacetGrid' object has no attribute 'get_xticklabels'.
but this worked:
g.fig.autofmt_xdate()

Categories

Resources