If I understand you correctly, then fill
would answer your question?
For instance,
mtcars %>%
ggplot(aes(x = factor(gear), group = factor(cyl), fill = factor(cyl))) +
geom_bar(position = "fill")

Here, you don't have the counts any longer, but for each value along the x
-axis, you have the percentage of each group (here: cylinder) plotted.
If this is not what you want, a general recommendation is to compute the data that you want to be plotted first, and then to plot it. That is, many people think it is generally advisable to separate computation/transformation/aggregation from plotting.
To follow up on my suggestion to separate computation from visualisation, let's consider the mtcars
dataset and focus on gear
and carb
.
with(mtcars, table(gear, carb))
carb
gear 1 2 3 4 6 8
3 3 4 3 5 0 0
4 4 4 0 4 0 0
5 0 2 0 1 1 1
For instance, you see that 3 (out of 32) observations have gear = 3, carb = 1
, which is a bit less than 10%. Similarly, 4 observations have gear = 4, carb = 1
, which is a bit more than 10%. Let's get the percentages directly:
with(mtcars, prop.table(table(gear, carb)))
carb
gear 1 2 3 4 6 8
3 0.09375 0.12500 0.09375 0.15625 0.00000 0.00000
4 0.12500 0.12500 0.00000 0.12500 0.00000 0.00000
5 0.00000 0.06250 0.00000 0.03125 0.03125 0.03125
I have used prop.table
here which also has a margin argument. That is, if you wanted to know conditional percentages, you could easily adjust this (see below). Let's stay with this for the time being, though. Let's say we want to visualize this now after we have computed the numbers, we could simply call the following:
with(mtcars, prop.table(table(gear, carb))) %>%
as.data.frame() %>%
ggplot(aes(x = factor(carb), y = Freq, group = factor(gear), fill = factor(gear))) +
geom_bar(stat = "identity")
which would give us:

Now imagine you want to get the conditional version, e.g.
with(mtcars, prop.table(table(gear, carb), margin = 1))
carb
gear 1 2 3 4 6 8
3 0.2000000 0.2666667 0.2000000 0.3333333 0.0000000 0.0000000
4 0.3333333 0.3333333 0.0000000 0.3333333 0.0000000 0.0000000
5 0.0000000 0.4000000 0.0000000 0.2000000 0.2000000 0.2000000
Notice how each row sums up to 1. This can be plotted in the same way:
with(mtcars, prop.table(table(gear, carb), margin = 1)) %>%
as.data.frame() %>%
ggplot(aes(x = factor(carb), y = Freq, group = factor(gear), fill = factor(gear))) +
geom_bar(stat = "identity")

Note the similarity to the smoothed version produced by:
mtcars %>%
ggplot(aes(x = factor(carb), group = factor(gear), fill = factor(gear))) +
geom_density(alpha = 0.5)
