Search code examples
rggplot2polar-coordinates

R coord_polar removes one segment


I try to build a radial plot with a segment that goes from just below 2*pi up to just above 2*pi. However, this segment is removed with the warning

Warning message:
Removed 1 row containing missing values or values outside the scale range
(`geom_line()`). 

Here is a MWE which generates the error and shows one case:

x=c( 0, 1, 2, 3, 4, 0, 1, 2, 3, 4.1)
y=c(10,12,17,13,10, 5, 6, 8, 7, 6)
grp = c(rep(1,5),rep(2,5))
df= data.frame(x = x, y = y, g = grp)

p1 <- ggplot(df, aes(x=x, y=y, group=g))+
  geom_line() + ylim(0,18) +
  coord_radial(clip="off",expand=FALSE) 
p2 <- ggplot(df, aes(x=x, y=y, group=g))+
  geom_line() + ylim(0,18) +
  coord_radial(clip="off",expand=FALSE) + xlim(0,4)

library(gridExtra)
grid.arrange(p1,p2,ncol=2)

two radial plots with the one on the right missing a segment

When I force the x-range to go from 0 to 4, the last segment ending at 4.1 is removed (I would prefer to see it truncated). I believed that (a) angles larger than 2*pi would be taken modulo 2*pi so that the line could continue; (b) using clip="off" would allow geom that extend a bit beyond their normal range to be plotted anyway (but clip seems to do nothing at all).

Is there a way to have geom extend beyond 2*pi? (I use ggplot2 version 3.5.1)


Solution

  • If you want the line to continue beyond the x limit, you can use scale_x_continuous(oob = scales::oob_keep):

    library(dplyr)
    library(ggplot2)
    library(gridExtra)
    
    p1 <- df  |> 
      ggplot(aes(x=x, y=y, group=g))+
      geom_line() + ylim(0,18) +
      coord_radial(expand=FALSE) +
      scale_x_continuous(limits = c(0, 4), oob = scales::oob_keep)
    

    If you want the line to be truncated, you can interpolate the y value at the limit:

    p2 <- df |> 
      mutate(xi = pmin(x, 4),
             yi = approx(x, y, xi)$y, .by = g) |> 
      ggplot(aes(x=xi, y=yi, group=g))+
      geom_line() + ylim(0,18) +
      coord_radial(expand=FALSE) +
      scale_x_continuous(limits = c(0, 4)) 
    
    grid.arrange(p1,p2,ncol=2)
    

    enter image description here