Peanut - 9 months ago 72
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:

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 Source

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, "%"))
``````

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.