How could I plot the relative frequency of data split into categories?

Viewed 207

I want to get the relative frequency of peoples weights based on a category label and then graph that as a bar chart that would look something like this:

enter image description here

The data frame looks like this:

Weight   Category
83.8     A
87.3     A
75.1     B
70.9     A
69.8     C
75.5     B
...      ...

I thought of extracting the weight of each category out into its own data frame and managed to get the relative frequency of one category, but I am unsure as to how to plot them all together.

# This holds the total number of people in each category, with categories in alphabetical order
counts = df.groupby("Category")["Weight"].count()

catA = df.loc[df["Category"] == "A"]["Weight"].reset_index().drop(columns="index")
catA["bucket"] = pd.cut(catA["Weight"], 10)

newA = catA[["bucket", "Weight"]].groupby("bucket").count()
newE["relative"] = newE["Weight"] / counts[0]

ax = newA["relative"].plot(kind="bar", title="Relative Frequency of Weight for Category A")
ax.set(xlabel="Weight Bucket", ylabel="Relative Frequency (%)")
ax.tick_params(axis="x", labelrotation=45)
plt.show()
2 Answers

Seaborn is a Python data visualization library based on matplotlib. It provides a high-level interface for drawing attractive and informative statistical graphics. (https://seaborn.pydata.org/)

you will not have the same flexibility as with raw matplotlib, but maybe it just works for you and gives you powerful defaults.

using a histplot with hue and multiple=dodge seems to do what you are looking for. from the official docs at https://seaborn.pydata.org/generated/seaborn.histplot.html#seaborn.histplot

sns.histplot(data=tips, x="day", hue="sex", multiple="dodge", shrink=.8)

seaborn

Use pd.cut to bucket your frequency, and pd.crosstab to count:

(pd.crosstab(pd.cut(df['Weight'], bins=np.linspace(0,100,10)),
             df['Category'])
   .plot.bar()
)
Related