-
Hi guys, I'm ploting a bar graph in fill mode, I have a main category and I'm counting occurences of a second category. Here's the result: I used a fill mapping for category2 and face_wrap for category 1. I would like that in each category, percentages sum up to 100% (and bar height are also wrong I think in my actual setup). How to do this? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Please provide a minimal code snippet. |
Beta Was this translation helpful? Give feedback.
-
When grouping gets complicated, like here where there are nested groups, it is better (and it may be the only way) to precompute the values and have them in a dataframe as well so that a straight mapping to that column is enough. However in this case, you can get away with this solution that relies on an internal variable import pandas as pd
import plotnine as p9
from mizani.labels import label_percent
d = pd.DataFrame({
"cat1": ["A","A","B","A","A","B","B","A","B","B","B","A","B","B","B","A","B"],
"cat2": ["W","X","Y","Z","W","X","Y","Z","W","X","Y","Z","W","X","Y","Z","X"]
}).assign(x=1)
def sum_by(col: pd.Series, by: pd.Series):
df = pd.DataFrame({col.name: col, "by": by})
return df.groupby("by", observed=False)[col.name].transform("sum")
(
p9.ggplot(d)
+ p9.geom_bar(p9.aes(x="x", fill="cat2"), stat="count", position="fill")
+ p9.geom_text(
p9.aes(
x="x",
group="cat2",
label=p9.after_stat("100*count/sum_by(count, PANEL)")
),
stat="count",
position=p9.position_fill(vjust=0.5),
format_string="{:.0f}%",
)
+ p9.facet_wrap("cat1")
+ p9.scale_y_continuous(labels=label_percent())
) |
Beta Was this translation helpful? Give feedback.
When grouping gets complicated, like here where there are nested groups, it is better (and it may be the only way) to precompute the values and have them in a dataframe as well so that a straight mapping to that column is enough.
However in this case, you can get away with this solution that relies on an internal variable
PANEL
.