I have a problem where sns.countplot won't work. I got the names of the most popular color in each year, and with that I'm trying to plot a countplot that will show number (count) of each of those color. Something like .value_counts() but in a graph.
Here is the code that I've written:
most_popular_color = df_merged_full.groupby('year')[['name_cr_invp_inv']].agg({lambda color_name: color_name.value_counts().idxmax()}).reset_index()
and it returns this (example not full file):
Now when I try to do the countplot:
sns.countplot(most_popular_color['name_cr_invp_inv'],
palette={color: color for color in most_popular_color['name_cr_invp_inv'].drop_duplicates()})
it returns an error: min() arg is an empty sequence.
Where is the problem, I can't find it?
From the question, it looks like you are trying to plot the number of entries with each color and map the color to the bar. For this, you just need to provide a dictionary with mapping of each color to the column value (which will be the same in this case) and use that as the palette. I have used the data you provided above and created this. As white is one of the colors, I have added a border so that you can see the bar. Hope this is what you are looking for...
## Create dictionary with mapping of colors to the various unique entries in data
cmap = dict(zip(df_merged_full.name_cr_invp_inv.unique(), df_merged_full.name_cr_invp_inv.unique()))
fig, ax = plt.subplots() ## To add border, we will need ax
ax=sns.countplot(x=df_merged_full.name_cr_invp_inv, palette=cmap) ## Plot with pallette=cmap
plt.setp(ax.patches, linewidth=1, edgecolor='black') ## Add border
Related
My problem is simple but I can't fix it.
I want to display a legend :
Based on my dictionary "color_dict" which defines colors, variables All in red and AML in blue, I want to display a legend. Porblem is, only the first one (All red) appears.
I have tried to use color_dict.keys to access the keys of my dictionary but it doesn't seem to work.
I don't understand the problem, why would ax.legend(color_dict.keys()) only take the first key/value pair of my dictionary ? How can I fix that?
Thanks for your help
More explainations if needed:
I want to plot the legend with 'All' in red and 'AML' in blue, but these variables are in my dictionary and when I try to access it with .keys in the ax.legend() from python, it only displays the first item as you can see on the picture.
`
l_dtprj2= list(zip(*data_proj2))
color_dict = {'ALL': 'red','AML': 'blue'}
x = l_dtprj2[0]
y= l_dtprj2[1]
colorName = list(df3['labels'])
fig, ax, = plt.subplots()
ax.scatter(x, y, c=df3['labels'].map(color_dict) )
plt.xlabel('Component 1') #x label
plt.ylabel('Component 2') #y label
ax.legend(color_dict.keys())
plt.show()`
My code AND its results (plot)
Here is the type of legend I'd like to have right below on the plot
I'm trying to create a barplot with custom colors based on one of the column in the df. However I don't want legend to display. As soon as I try to remove legend color is back to default.
Here is my code.
b = sns.barplot(x="game_week", y="shots", data=data, hue="color")
b.tick_params(labelsize=5)
b.legend_.remove()
b.set(ylim=(0, np.nanmax(df[cols])))
Any ideas? Is it even possible with sns.barplot?
You can set the color palette with seaborn.color_palette like this:
palette = sns.color_palette('hls', len(data.color.unique())
ax = sns.barplot(
x="game_week",
y="shots",
data=data,
hue="color",
palette=palette
)
ax.legend_.remove()
By setting the palette this way you will get a number of colors corresponding to the number of categories in the color column of your dataframe that is also colorblind friendly!
I've seen Creating multi column legend in python seaborn plot but I think my question is a bit different. In short, I've got a dataframe that I'm plotting in seaborn's lmplot and getting a FacetGrid. Trouble is, there are tons of values for hue so I get a super long, single column legend. Code example below:
ers = sns.lmplot(
data=emorb,
x="Pb",
y="Nd",
row="Ridge Sys",
hue="Seg Name",
scatter=True,
fit_reg=False,
scatter_kws={"alpha":0.7, "edgecolor": "w"},
palette=sns.color_palette("bright", 20),
legend=True
)
ers.set(ylim=(0.5122,0.5134))
I can access the legend object that is created by calling ers._legend and this returns an object with type Legend (basically, a matplotlib object). However, I can't then call to this legend object to change the number of columns, e.g., with:
l = ers._legend
l(ncols=9)
Any suggestions, or am I missing something perhaps more obvious, such as a way to redraw the legend and specify any parameters?
Thanks.
Whoops, figured it out:
The FacetGrid object has an attribute fig, i.e.
g = sns.lmplot()
parent_mpl_figure = g.fig
And so if I set legend=False in sns.lmplot(), I can then specify parent_mpl_figure.legend(labels=[], ncol=9, bbox_to_anchor=(1,1)).
Written cleanly:
g = sns.lmplot(legend = False)
parent_mpl_figure = g.fig
parent_mpl_figure.legend(labels = [], ncol = 9, bbox_to_anchor = (1,1))
Hope this is instructive for someone else / now to figure out how to have each Facet span the full color palette so that different hue groups within each Facet group are easier to distinguish...
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.
I am creating a stacked plot. I understand, from experimenting myself and from researching online, that adding labels to a stacked plot is messy, but I have managed to pull it off with the code below.
My question is: how do I retrieve the color cycle used to create the stacked plot, so that I can assign the right colours to the legend?
Right now field 1 is blueish, field 2 greenish, but both labels appear in the first colour. I can force specific colours to both the plot and the legends, but I quite like the default colour cycle and would like to keep using it.
df=pd.DataFrame(np.ones((10,2)),columns=['field1','field2'])
fig,ax=plt.subplots()
plt.suptitle('This is a plot of ABCDEF')
ax.stackplot(df.index,df.field1,df.field2]
patch1=matplotlib.patches.Patch(color='red',label= 'field 1')
patch2=matplotlib.patches.Patch(color='blue', label ='field 2')
plt.legend(handles=[patch1,patch2])
The closest to a solution I have found is: Get matplotlib color cycle state but, if I understand correctly, the order of the colours is not preserved. The problem is that
ax._get_lines.color_cycle
returns an iterator, not a list, so I can't easily do something like
colour of patch 1 = ax._get_lines.color_cycle[0]
Thanks!
You can get the colors from the polycollection object made by stackplot:
fields = ax.stackplot(df.index,df.field1,df.field2)
colors = [field.get_facecolor()[0] for field in fields]
patch1=mpl.patches.Patch(color=colors[0],label= 'field 1')
patch2=mpl.patches.Patch(color=colors[1], label ='field 2')