How to make an overlapping barplot?

非 Y 不嫁゛ 提交于 2019-12-18 04:19:19

问题


Making a barplot the 'standard' way

dat <- read.table(text = "A   B 
+ 1 1 4
+ 2 2 3
+ 3 3 2
+ 4 4 1", header = TRUE)
barplot(as.matrix(dat))

gives a barplot like this:

Instead, I would like to have the different segnments to overlap, like so

How can I make such a plot in R?


回答1:


There are two ways I have used:

(counts <- with(diamonds, table(cut, clarity)))
#            clarity
# cut           I1  SI2  SI1  VS2  VS1 VVS2 VVS1   IF
# Fair         210  466  408  261  170   69   17    9
# Good          96 1081 1560  978  648  286  186   71
# Very Good     84 2100 3240 2591 1775 1235  789  268
# Premium      205 2949 3575 3357 1989  870  616  230
# Ideal        146 2598 4282 5071 3589 2606 2047 1212

It is painfully easy in ggplot

library(ggplot2)
ggplot(diamonds, aes(clarity, fill = cut)) + 
  geom_bar(position = 'identity', alpha = .3)

In base R

par(xpd = TRUE, mar = c(4,4,2,2))
invisible(sapply(1:nrow(counts), function(x)
  barplot(counts[x, ], axes = FALSE, axisnames = FALSE,
          main = 'identity', border = NA,
          col = tcol(ggcols(5)[x], 50), 
          axis.lty = 1, ylim = c(0, 5000), 
          add  = ifelse(x == 1, FALSE, TRUE))))
axis(1, at = barplot(counts, plot = FALSE), labels = colnames(counts))
axis(2, at = seq(0, 5000, 1000), labels = seq(0, 5000, 1000))
legend('topright', bty = 'n', title = 'cut',
       legend = rownames(counts), fill = tcol(ggcols(5), 100))

I used this transparent color function from a personal package:

#' Transparent colors
#' 
#' Add transparency to colors
#' 
#' @usage tcol(color, trans = 255)
#' 
#' @param color single or string of color names (or hexadecimal format) 
#' @param trans transparency defined as an integer in the range 
#' \code{[0, 255]} where \code{0} is fully transparent and \code{255} is fully
#' visible; see details
#' 
#' @details This is a vectorized function to add transparency to colors. 
#' \code{color} and \code{trans} must either be the same length or one of the 
#' two must have length one. 
#' 
#' The function adds integers (in hex) between 0 (fully transparent) and 255
#' (fully visible) to the color(s) given. \code{color} values are converted to
#' RGB with transparency.
#' 
#' @seealso \code{\link{num2hex}}, \code{\link{col2rgb}}
#' 
#' @examples
#' cols <- c('red','green','pink')
#' 
#' # a normal plot
#' plot(rnorm(100), col = tcol(cols), pch = 16, cex = 4)
#' 
#' # more transparent
#' plot(rnorm(100), col = tcol(cols, 100), pch = 16, cex = 4)
#' 
#' # hexadecimal colors also work
#' cols <- c('#FF0000','#00FF00','#FFC0CB')
#' plot(rnorm(100), col = tcol(cols, 200), pch= 16, cex = 4)
#' @export

tcol <- function(color, trans = 255) {

  if (length(color) != length(trans) & 
        !any(c(length(color), length(trans)) == 1)) 
    stop('Vector lengths not correct')
  if (length(color) == 1 & length(trans) > 1) 
    color <- rep(color, length(trans))
  if (length(trans) == 1 & length(color) > 1) 
    trans <- rep(trans, length(color))

  res <- paste0('#', apply(apply(rbind(col2rgb(color)), 2, function(x) 
    format(as.hexmode(x), 2)), 2, paste, collapse = ''))
  res <- unlist(unname(Map(paste0, res, as.character(as.hexmode(trans)))))
  res[is.na(color)] <- NA
  return(res)
}

And to match the ggplot colors:

ggcols <- function (n, l = 65, c = 100) {
    hues <- seq(15, 375, length = n + 1)
    hcl(h = hues, l = l, c = c)[1:n]
}



回答2:


In plain R overlapping bar plots can also be achieved by :

1 - making bars transparent using the alpha value of the rgb function call (e.g., rgb(redValue, greenValue, blueValue, alphaLevel) by which rgb(1, 0, 0, .5) corresponds to red with an alpha level of .5)

2 - adding different bar plots on top of each other using the option add=TRUE in the call to barplot Or in code:

dat <- read.table(text = "A   B
  1 4
  2 3
  3 2
  4 1", header = TRUE)

barplot(dat$A, col=rgb(1, 0, 0, .5)) 
barplot(dat$B, col=rgb(0, 1, 0, .5), add=TRUE) 

# adding a legend
legend('top', bty = 'n', title = 'Legend',
  legend = c('A', 'B'), fill = c('red', 'green'))

The plot can be further prettified, but I believed this code provides a very simple alternative which would do the trick.



来源:https://stackoverflow.com/questions/23228082/how-to-make-an-overlapping-barplot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!