0

I am trying to create a donut chart and am having difficulty adding color gradient. I want to be able to take all of the different categories and fade them from whatever color they are to white. Is there an easy way to do this?

data<-data.frame(count=c(39,36,19,6), category=c("a","b","c","d"))
data$fraction = data$count / sum(data$count)
data = data[order(data$fraction), ]
data$ymax = cumsum(data$fraction)
data$ymin = c(0, head(data$ymax, n=-1))

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Create Plot
fill <- c("blue3","cyan3","darkgrey","forestgreen")

p1 = ggplot(data, aes(fill=category, ymax=ymax, ymin=ymin, xmax=4, xmin=3.5)) 
+ geom_rect(colour="White") +
 coord_polar(theta="y") +
 scale_fill_manual(values=fill)+
 theme_bw()+
 theme(panel.grid=element_blank())+
 theme(axis.ticks=element_blank()) +     
 xlim(c(0, 4)) +
 theme(axis.text=element_blank()) +
 labs(title="donut plot")


 print(p1)
Sam Miranda
  • 121
  • 1
  • 1
  • 8
  • This previous question might help... http://stackoverflow.com/questions/20069660/r-gradient-fill-for-geom-rect-in-ggplot2 – Andrew Gustar Apr 24 '17 at 16:39
  • That is assigning different colors to different values to different rankings creating the faded look. What I'm trying to do is have the color for each value have a gradient effect. So for category "a" I would want the piece to fade from "white" to "cyan3" – Sam Miranda Apr 24 '17 at 16:45

2 Answers2

0

Use the alpha values to control the shading within each category.

library(ggplot2)
library(dplyr)

N    <- 100
fill <- c("blue3","cyan3","darkgrey","forestgreen")

data          <- data.frame(count = c(39,36,19,6), category = c("a","b","c","d"))
data$fraction <- data$count / sum(data$count)
data          <- data[order(data$fraction), ]
data$ymax     <- cumsum(data$fraction)
data$ymin     <- c(0, head(data$ymax, n = -1))

data2 <-
  data.frame(count = rep(data$count, each = N),
             category = rep(data$category, each = N),
             ymin = c(0,
                      seq(0.00, 0.06, length = N),
                      seq(0.06, 0.25, length = N),
                      seq(0.25, 0.61, length = N),
                      seq(0.61, 1.00, length = N)[-N]),
             ymax = c(seq(0.00, 0.06, length = N)[-1],
                      seq(0.06, 0.25, length = N),
                      seq(0.25, 0.61, length = N),
                      seq(0.61, 1.00, length = N),
                      1.00))
data2$y <- with(data2, (ymin + ymax)/2)

data2 <- 
  data2 %>%
  group_by(category) %>%
  mutate(alpha = (y - min(y)) / max(y)) %>%
  ungroup()

ggplot(data2) +
  aes(ymax = ymax, ymin = ymin, xmax = 4, xmin = 3.5, fill = category, alpha = alpha) + 
  geom_rect() +
  coord_polar(theta = "y") +
  theme_bw()+
  theme(panel.grid=element_blank()) +
  theme(axis.ticks=element_blank()) +     
  xlim(c(0, 4)) +
  theme(axis.text=element_blank()) +
  labs(title="donut plot") +
  scale_fill_manual(values = fill) +
  guides(alpha = "none")

enter image description here

Peter
  • 7,460
  • 2
  • 47
  • 68
  • That work perfectly and looks great in R but is there a way to do this without making it so that it is a million different pieces? When it gets exported out of R and to a document you can see each individual line. – Sam Miranda Apr 25 '17 at 15:37
  • @SamMiranda, what file format are you using to export the image? – Peter Apr 25 '17 at 17:36
  • I'm not exporting it as an an image. I used addPlot to add it to a powerpoint – Sam Miranda Apr 25 '17 at 17:57
  • have you tried setting `vector.graphic = TRUE` in the `addPlot` call? – Peter Apr 25 '17 at 18:25
  • 1
    You need to increase `N` (try 200 or 500) in this code to keep the individual steps from showing as discrete `geom_rect`angles. Be forewarned, outputting large numbers of elements with varying `alpha` will be slow, but it will end up looking good. – Brian Apr 25 '17 at 21:54
0

It is not possible to do this directly, as far as I know, but you could achieve a similar effect by expanding your data frame and setting an alpha value dependent on the radius. Something like this...

data<-data.frame(count=c(39,36,19,6), category=c("a","b","c","d"))
data$fraction = data$count / sum(data$count)
data = data[order(data$fraction), ]
data$ymax = cumsum(data$fraction)
data$ymin = c(0, head(data$ymax, n=-1))

data <- as.data.frame(lapply(data,rep,10))
data$xmin <- rep(0:9,each=4)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Create Plot
fill <- c("blue3","cyan3","darkgrey","forestgreen")

p1 = ggplot(data, aes(fill=category, ymax=ymax, ymin=ymin, xmin=xmin, xmax=xmin+1)) + geom_rect(aes(alpha=xmin/9)) +
  coord_polar(theta="y") +
  scale_fill_manual(values=fill)+
  scale_alpha_continuous(guide=FALSE)+
  theme_bw()+
  theme(panel.grid=element_blank())+
  theme(axis.ticks=element_blank()) +     
  theme(axis.text=element_blank()) +
  labs(title="donut plot")

print(p1)

enter image description here

Andrew Gustar
  • 17,295
  • 1
  • 22
  • 32