ggplot2 pie and donut chart on same plot

前端 未结 6 1788
花落未央
花落未央 2020-11-28 03:35

I am trying to replicate this \"enter with R ggplot. I have exactly the same data:

<         


        
6条回答
  •  广开言路
    2020-11-28 04:09

    @rawr's solution is really nice, however, the labels will be overlapped if there are too many. Inspired by @user3969377 and @FlorianGD, I got a new solution using ggplot2 and ggrepel.

    1. prepare data

    browsers$ymax <- cumsum(browsers$share) # fed to geom_rect() in piedonut()
    browsers$ymin <- browsers$ymax - browsers$share # fed to geom_rect() in piedonut()
    
    browsers$share_browser <- sum(browsers$share[browsers$browser == unique(browsers$browser)[1]]) # "_browser" means at browser level
    browsers$ymax_browser <- browsers$share_browser[browsers$browser == unique(browsers$browser)[1]][1]
    for (z in 2:length(unique(browsers$browser))) {
      browsers$share_browser[browsers$browser == unique(browsers$browser)[z]] <- sum(browsers$share[browsers$browser == unique(browsers$browser)[z]])
      browsers$ymax_browser[browsers$browser == unique(browsers$browser)[z]] <- browsers$ymax_browser[browsers$browser == unique(browsers$browser)[z-1]][1] + browsers$share_browser[browsers$browser == unique(browsers$browser)[z]][1]
    }
    browsers$ymin_browser <- browsers$ymax_browser - browsers$share_browser
    

    2. write piedonut function

    piedonut <- function(data, cols = c('cyan2','red','orange','green','dodgerblue2'), force = 80, nudge_x = 3, nudge_y = 10) { # force, nudge_x, nudge_y are parameters to fine tune positions of the labels by geom_label_repel.
      nr <- nrow(data)
      # width <- max(sqrt(data$share)) / 0.1
      
      tbl <- with(data, table(browser)[order(unique(browser))])
      cols <- unlist(Map(rep, cols, tbl))
      col_subnum <- unlist(Map(rep, 255/tbl,tbl))
      
      col <- rep(NA, nr)
      col_browser <- rep(NA, nr)
      for (i in 1:nr) {
        ## create color/shades
        rgb <- col2rgb(cols[i])
        col[i] <- rgb(rgb[1], rgb[2], rgb[3],  col_subnum[i]*sequence(tbl)[i], maxColorValue = 255)
      
        rgb <- col2rgb(cols[i])
        col_browser[i] <- rgb(rgb[1], rgb[2], rgb[3], maxColorValue = 255)
      }
      #col
      # set labels positions
      x.breaks <- seq(1, 1.8, length.out = nr)
      y.breaks <- cumsum(data$share)-data$share/2
      ggplot(data) +
        geom_rect(aes(ymax = ymax, ymin = ymin, xmax=4, xmin=1), fill=col) +
        geom_rect(aes(ymax=ymax_browser, ymin=ymin_browser, xmax=1, xmin=0), fill=col_browser) +
        coord_polar(theta = 'y') +
        theme(axis.ticks = element_blank(),
              axis.title = element_blank(),
              axis.text = element_blank(),
              panel.grid = element_blank(),
              panel.background = element_blank()) +
        geom_label_repel(aes(x = x.breaks, y = y.breaks, label = sprintf("%s: %s%%",data$version, data$share)),
                         force = force,
                         nudge_x = nudge_x,
                         nudge_y = nudge_y)
    }
    

    3. get the piedonut

    cols <- c('cyan2','red','orange','green','dodgerblue2')
    
    pdf('~/Downloads/donuts.pdf', width = 10, height = 10, bg = "snow")
    par(omi = c(0.5,0.5,0.75,0.5), mai = c(0.1,0.1,0.1,0.1), las = 1)
    print(piedonut(data = browsers, cols = cols, force = 80, nudge_x = 3, nudge_y = 10))
    dev.off()
    

提交回复
热议问题