Peanut Peanut - 4 days ago 5
R Question

Add values to bars in stacked horizontal barplot using R base

I found a plot in a stats book, which I want to reproduce with the base package.

The plot looks like this:

enter image description here

So far I have the plot, but I have problems to add a centred labels to each part of the bar.

My code looks like this:

data <- sample( 5, 10 , replace = TRUE )

colors <- c('yellow','violet','green','pink','red')

relative.frequencies <- as.matrix( prop.table( table( data ) ) )

bc <- barplot( relative.frequencies, horiz = TRUE, axes = FALSE, col = colors )

Answer

For your given example, we can do:

set.seed(0)  ## `set.seed` for reproducibility
dat <- sample( 5, 10 , replace = TRUE )
colors <- c('yellow','violet','green','pink','red')
h <- as.matrix( prop.table( table( dat ) ) )
bc <- barplot(h, horiz = TRUE, axes = FALSE, col = colors )
## compute x-location of the centre of each bar
H <- apply(rbind(0, h[-nrow(h), ]), 2L, cumsum) + h / 2
## add text
text(H, bc, labels = paste0(100 * h, "%"))

enter image description here

In the above, computation of H is the key. It is related to how barplot determines the height of the bar to plot when producing stacked bar-chart.

We first consider the vector case. If you have a vector of height, say h, then the height of stacked bar-chart is cumsum(h). So the centre of each stacked bar is

cumsum(c(0, h))[-length(h)] + h

Now if we have a matrix input h, we simply want to use apply to apply the above to all columns (Margin: 2) of h, hence we want:

apply(rbind(0, h)[-nrow(h)], 2L, cumsum) + h / 2

Finally we use text for add text to the plot.