I have a dataframe such as :
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Sample data
data = {
'genus': ['SpeciesA', 'SpeciesB', 'SpeciesC', 'SpeciesD', 'SpeciesE', 'SpeciesF', 'SpeciesG', 'SpeciesH'],
'count': [10, 2, 1, 1, 1, 1, 1, 1],
'Type': ['Animal', 'Environment', 'Environment', 'Environment', 'Animal', 'Animal', 'Animal/Environment', 'Animal/Environment']
}
# Create DataFrame
df = pd.DataFrame(data)
>>> df
genus count Type
0 SpeciesA 10 Animal
1 SpeciesB 2 Environment
2 SpeciesC 1 Environment
3 SpeciesD 1 Environment
4 SpeciesE 1 Animal
5 SpeciesF 1 Animal
6 SpeciesG 1 Animal/Environment
7 SpeciesH 1 Animal/Environment
And I would like using python to create a pie chart were the piechart is divided into each Type proportional to its total count
So far I can do that using :
# Group by 'Type' and sum up 'count' within each group
type_counts = df.groupby('Type')['count'].sum()
# Create pie chart
plt.figure(figsize=(8, 8))
plt.pie(type_counts, labels=type_counts.index, startangle=140)
plt.title('Distribution of Counts by Type')
plt.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
plt.show()
But I am now looking for a way to add the genus labels within the specific sub-pie chart part.
Such labels should be included in this way (A):
In such a way that the labels are placed randomly in the corresponding pie chart without overlapping by optimizing the space.
Or, if it is impossible to simply place them in this way (B):
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
data = {
'genus': ['SpeciesA', 'SpeciesB', 'SpeciesC', 'SpeciesD', 'SpeciesE', 'SpeciesF', 'SpeciesG', 'SpeciesH'],
'count': [10, 2, 1, 1, 1, 1, 1, 1],
'Type': ['Animal', 'Environment', 'Environment', 'Environment', 'Animal', 'Animal', 'Animal/Environment', 'Animal/Environment']
}
df = pd.DataFrame(data)
plt.figure(figsize=(20, 20))
fig, ax = plt.subplots()
size = 0.45
cmap = plt.get_cmap("tab20c")
outer_colors = cmap(np.arange(3)*4)
inner_colors = cmap(np.array([1, 2, 5, 6, 9, 10, 11, 12]))
ax.pie(df.groupby('Type', sort=False)['count'].sum(), colors=outer_colors, radius=1, labels=df['Type'].drop_duplicates(), autopct='%.0f%%', textprops={'size': 'smaller'}, pctdistance = 1.1,
labeldistance = 1.2,)
ax.pie(df['count'], radius=1-size, colors=inner_colors, labels=df['genus'], autopct='%.0f%%', textprops={'size': 'smaller', 'color':"w"}, labeldistance=1, rotatelabels = 270)
plt.show()
Output: