Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap around the polar coordinate limits in ggplot2?

I have a circular space where angles 0 and 360 are equivalent. I want to plot rectangles in this space such that rectangles can cross this value. However, I am having trouble with ggplot2.

base <- ggplot() +
  scale_x_continuous(breaks = seq(45, 360, 45), limits = c(0, 360)) +
  scale_y_continuous(breaks = seq(0, 1, 0.2), limits = c(0, 1)) +
  coord_polar(theta = "x", start = 1.5 * pi, direction = -1)

enter image description here

1. Attempt to plot with values exceeding xlim:

base + geom_rect(aes(xmin = 340, xmax = 380, ymin = 0.4, ymax = 0.6), 
  color = "darkblue", fill = "steelblue")
#> Warning message:
#> Removed 1 rows containing missing values (geom_rect). 

All values outside of xlim are removed so this does not work.

2. Attempt to plot with rescaled values

base + geom_rect(aes(xmin = 340, xmax = 380 %% 360, ymin = 0.4, ymax = 0.6), 
  color = "darkblue", fill = "steelblue")

enter image description here This at least produces a plot, but plots the opposite of what I want. Instead of going from 340 to 380 CCW, this plots 340 to 20 CW.

3. Attempt to plot as two conjoining elements

  base + geom_rect(aes(xmin = c(350, 0), xmax = c(360, 10), ymin = 0.4, ymax = 0.6), 
    color = "darkblue", fill = "steelblue")

enter image description here

This shows the rectangle where I want it, but this is not satisfying as a solution because of the stroke lines at angle 0/360 and because I now have to represent each rectangle as two rectangles.

4. Attempt 1 to use zooming rather than clipping

ggplot() +
  scale_x_continuous(breaks = seq(45, 360, 45)) +
  scale_y_continuous(breaks = seq(0, 1, 0.2), limits = c(0, 1)) +
  coord_cartesian(xlim = c(0, 360)) +
  coord_polar(theta = "x", start = 1.5 * pi, direction = -1) +
  geom_rect(aes(xmin = 340, xmax = 380, ymin = 0.4, ymax = 0.6), 
    color = "darkblue", fill = "steelblue")

enter image description here This seems to lose the zooming and the limits.

5. Attempt 2 to use zooming rather than clipping

ggplot() +
  scale_x_continuous(breaks = seq(45, 360, 45)) +
  scale_y_continuous(breaks = seq(0, 1, 0.2), limits = c(0, 1)) +
  coord_polar(theta = "x", start = 1.5 * pi, direction = -1) +
  coord_cartesian(xlim = c(0, 360)) +
  geom_rect(aes(xmin = 340, xmax = 380, ymin = 0.4, ymax = 0.6), 
    color = "darkblue", fill = "steelblue")

enter image description here This accomplishes the zooming correctly, but overwrites the polar coordinate system.

If anyone can provide a solution or ideas for this problem, I would really appreciate it. Again, I am looking for something that looks like #3 but without the inner stroke and without needing to use two rectangles.

Edit: This question is related and also unanswered.

like image 507
Jeffrey Girard Avatar asked Dec 11 '17 19:12

Jeffrey Girard


People also ask

How many coordinate systems does ggplot2 have?

16 Coordinate systems | ggplot2.

What does coord_ fixed do in r?

It allows drawing of data points anywhere on the plot, including in the plot margins. If limits are set via xlim and ylim and some data points fall outside those limits, then those data points may show up in places such as the axes, the legend, the plot title, or the plot margins.

How do you plot points in polar?

To plot a point in the polar coordinate system, start with the angle. If the angle is positive, then measure the angle from the polar axis in a counterclockwise direction. If it is negative, then measure it clockwise. If the value of r r is positive, move that distance along the terminal ray of the angle.

Which coordinate system do pie charts use?

The polar coordinate system is most commonly used for pie charts, which are a stacked bar chart in polar coordinates.


1 Answers

Is it critical that the underlying coordinate system is polar? geom_arc_bar() from the ggforce package behaves as you would expect, so you can use it to draw arcs in arbitrary angles. But you have a cartesian coordinate system underneath, so you may have to draw the coordinate lines yourself if you need them.

library(ggforce)
library(dplyr)

data_deg <- data.frame(xmin = 340,
                   xmax = 380,
                   ymin = 0.4,
                   ymax = 0.6)

offset = 90 # by how much are angles offset
dir = 1 # should we go counterclockwise (1) or clockwise (-1)

# convert angles from degrees into radians, apply offset and direction
data_rad <- mutate(data_deg,
               xmin = dir*2*pi*(xmin + offset)/360,
               xmax = dir*2*pi*(xmax + offset)/360)

ggplot(data_rad) + geom_arc_bar(aes(x0 = 0, y0 = 0, r0 = ymin, r = ymax,
                                start = xmin, end = xmax),
                            color = "darkblue", fill = "steelblue") +
  scale_x_continuous(limits = c(-1, 1)) +
  scale_y_continuous(limits = c(-1, 1)) +
  coord_fixed()

enter image description here

This doesn't solve the other issue you linked to, but in general you will probably find that converting coordinates from polar to Euclidean yourself gives you much more flexibility to get the plot looking the way you want it to.

like image 117
Claus Wilke Avatar answered Oct 13 '22 19:10

Claus Wilke