Reputation: 27
percentage_df = df.groupby(['customer service calls', 'churn']).size().groupby(level=0).apply(
lambda x: np.round(x * 100 / len(df), 2))
ax = percentage_df.unstack().plot(kind='bar', stacked=True, figsize=(10,10))
for c in ax.containers:
ax.bar_label(c, label_type='center',color='black')
outcome :
Hi, I am new to python, and the below image is what I am planning to code.
the bar should be the same, but percentage indicates the percentage of the certain group
add % sign
only shows the percentage of orange parts
#1 is the main problem I am having with.
Would you please help me on this problem? Many thanks in advance.
Upvotes: 1
Views: 131
Reputation: 919
Is that what you want ? (I used bar containers to edit the bars data and a little of list comprehension) :
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
# init df:
df = pd.DataFrame({'calls':[np.random.randint(0,10) for _ in range(40)],
'churn': [random.choice([True, False]) for _ in range(40)]})
# preprocess the dataframe:
# true and false values calculation
true_perc = df.groupby('calls')['churn'].mean()*100
true_count = df.groupby('calls')['churn'].sum()
false_count = df.groupby('calls')['churn'].count() - df.groupby('calls')['churn'].sum()
# final df
df = pd.concat([false_count, true_count], axis=1)
df.columns = ['false_count', 'true_count']
# create plot
ax = df.plot( kind='bar', stacked=True, figsize=(10,10))
# getting the containers values
container_t = ax.containers[1]
# create custom labels
labels = [f'{round(val, 2)} %' if (val != 0) else '' for val in true_perc]
# annotate with the previous custom labels
ax.bar_label(container_t, labels=labels, label_type='center', fontsize=7)
# pad the spacing between the number and the edge of the figure
ax.margins(y=0.1)
# show plot
plt.show()
output:
Upvotes: 1