Search code examples
rggplot2geometryfillggforce

ggplot2 function for filling a circle under a horizonal line?


I am trying to plot a circle in R, then fill a portion above a horizontal line with one color, and a portion below a horizontal line with another color, but I can't quite get it to work.

I've gotten so far as to draw the circle I want, plot a rectangle on top to "erase" the portion of the circle that should be transparent. However, I can't do a similar thing to get the other portion of the circle to layer on top because the white rectangle would cover the first circle.

Ideally, I'd love a way to just define a chord and then remove anything on one side of the chord.

Here's the simple code I have now and an example of what it creates:

ggplot()+
  geom_circle(aes(x0=0,y0=0,r=1,fill="red"),color=NA)+
  geom_rect(aes(xmin=-1,ymin=-0.5,xmax=1,ymax=1),fill="white",color=NA)+
  theme_void()

only bottom half

I was hoping to produce a full circle with the portion seen above in red and the rest of the circle filled in blue.

If it helps, here's the answer for what I want to do in python! How to draw a filled arc in matplotlib But not in R.


Solution

  • Use ggforce::geom_circle() to make the larger portion of the circle, and ggplot2::geom_ribbon() to make the smaller portion. You’ll have to compute the points for geom_ribbon() manually as shown in my example.

    library(dplyr)
    library(ggplot2)
    library(ggforce)
    
    y_cut <- -.5
    
    c_pts <- tibble(
        deg = 0:360,
        r = 1,
        x = r * cos((deg * pi)/180), 
        y = r * sin((deg * pi)/180)
      ) %>%
      filter(y <= y_cut)
    
    
    ggplot() +
      geom_circle(
        aes(x0 = 0, y0 = 0, r = 1), 
        fill = "blue", 
        color = NA
      ) +
      geom_ribbon(
        data = c_pts, 
        aes(x, ymin = y, ymax = y_cut), 
        fill = "red", 
        color = NA
      ) +
      theme_void()