9

I am trying to draw two points in polar coordinates (r, theta), where r is a distance from the center, and theta the angle.

The current solution does not work because I don't have a unique "origin" of the axes. When using coord_plane, the origin of y is the center of the circle, but the origin of x seems to be the center of each radius.

What I am trying to do, is to plot in a system where the two points from the below example are symmetric with respect to the origin.

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

enter image description here

UPDATE:

While the system that coord_polar creates is probably not a "straight" polar systems, here is a quote from the grammar of graphics that in part explains in part the behavior of coord_polar, and the reason why I had to fix the limits of y:

We could treat polar coordinates as an exception to the way all other scales are handled in this system. That is, we could interpret angular values ab- solutely as radians. This would make sense if all our graphics were mathemat- ical or engineering applications involving radians. We have chosen not to do this, however, so that we can hide scaling details when doing coordinate con- versions. This makes it easy, for example, to represent yearly time in polar co- ordinates. In the polar coordinate conversion, therefore, we align 0 radians with the minimum scale value in data units (degrees, radians, proportions, etc.) and 2S radians with the maximum. The cycle parameter, together with min and max parameters in the scale functions allows us to create polar graphs with more than one revolution if we wish.

Dambo
  • 3,318
  • 5
  • 30
  • 79
  • I'd think the key here (and used in two answers) is to convert *"negative r"* to *"positive r, `pi` radians around the circle"*. With that, the solution is in *adapting the data*, at which point plotting it works itself out. – r2evans Jul 23 '19 at 21:27
  • @r2evans the problem for me is how that solution "scales" to other operations. For instance, plotting the equation of a straight line in polar coordinates. – Dambo Jul 25 '19 at 04:31
  • I understand your concern, and I think that that is how it looks and behaves, so I think it is correct. Conceptually, what *is* the difference between "1 at 45deg" and "-1 at 225deg"? Don't they plot (by hand) to the same place on a polar graph? – r2evans Jul 25 '19 at 15:05
  • @r2evans I am not sure I get your point, but regarding "correctness": I quoted in a comment to antoine-sac's response a passage from the Grammar of Graphics which explains the default behavior, which is admittedly not "correct" in a mathematical sense, but the authors give a good reason for such convention. For me, one side-effect is that I have an equation of a straight line in polar coordinates, and the equation is plotted incorrectly (and by "incorrectly" I mean not in a normal polar system). – Dambo Jul 25 '19 at 15:13
  • Plotting *points* seems correct from my perspective, but now that you mention "line", I can see where you have a problem. Is it correct that, if it were plotted correctly, adding `geom_line` to the above would have a cartesian-straight-line between the points on opposing sides of the origin, vice the current plot of an arc on `r=100`? (If you have a cartesian equation for a line, perhaps converting it to polar could be done as demonstrated [here](https://math.stackexchange.com/a/2736244/248506).) – r2evans Jul 25 '19 at 18:45
  • 1
    @r2evans That's exactly what I did, deriving the equation of what would look like a straight line in polar coordinates, and it doesn't work with `coord_polar` because that is not a polar system. To your other point: the fact the `geom_line` looks like an arc in `coord_polar` makes total sense to me. However, I think I actually found an inconsistency with the grammar which is how `geom_area` is rendered: that geom should keep contour lines straight even in polar coordinates. – Dambo Jul 25 '19 at 18:58
  • @r2evans I was going off-topic so I opened another question regarding this issue if you have any ideas https://stackoverflow.com/questions/57209060/how-to-draw-a-radar-plot-in-ggplot-using-polar-coordinates – Dambo Jul 25 '19 at 19:37

3 Answers3

7

I don't fully understand what is your ultimate goal, but maybe the problem is that if you want r to represent distance to the origin, then it cannot be negative. What ggplot2 does with coord_polar() is just to deform the whole cartesian plane following polar coordinates. This results in a "zero" that is actually the lower limit of your "radial" coordinate. You can see it clearly if you manually change its limits:

library(ggplot2)
ggplot(data.frame(r = c(-100, 100) , theta = c(1, 1)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(-200, NA))

I don't know exactly what you mean with "symmetric with respect to the origin" but something this would be ok?

library(ggplot2)
ggplot(data.frame(r = c(100, 100) , theta = c(1, 1 + pi)),
       aes(x = r, y= theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y',
              direction = -1,
              start = -pi/2) +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi')) +
  scale_x_continuous(limits = c(0, NA))

Created on 2019-07-16 by the reprex package (v0.3.0)

Elio Campitelli
  • 1,408
  • 1
  • 10
  • 20
  • Thanks for answering. Picture number 2 is actually what I am looking for, and what you would get if the plane was an "actual" polar plane. My end goal is to plot a straight line on a polar plane - but first I need to figure out how to plot a dot... – Dambo Jul 16 '19 at 22:16
  • 1
    @Dambo if the end result is a straight line, consider generic annotation, e.g with `cowplot` (https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html) - just create a line as second plot and overlay. Might be a straight forward hack for the purpose. – tjebo Jul 17 '19 at 17:45
  • @Tjebo unfortunately not an option for me, I need to draw the line in polar coordinates. – Dambo Jul 18 '19 at 14:56
6

Adapting Elio Campitelli's answer as a function, you could use something like:

plot_polar_signed <- function(r, theta) {
  data2 <- data.frame(r2 = abs(r),
             theta2 = theta + ifelse(r < 0, pi, 0))
  ggplot(data2, aes(x = r2, y = theta2)) +
    geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
    coord_polar(theta = 'y',
                direction = -1,
                start = -pi/2) +
    scale_y_continuous(limits = c(0, 2*pi),
                       breaks = c(0, pi/2, pi, 3*pi/2 ),
                       labels = c('0', 'pi/2', 'pi', '3/2pi'))

}

plot_polar_signed(r = c(-100, 100), theta = c(1, 1))

enter image description here

Jon Spring
  • 55,165
  • 4
  • 35
  • 53
3

Points with r < 0 are not defined in polar coordinates, since r is the distance from the center. Otherwise there would be 2 sets of coordinates for every point with r != 0 even when forcing theta to be in (0, 2pi).

So you're really trying to plot in an extended polar coordinate system where negative r is allowed and (r, theta) and (-r, theta + pi) are the same points.

I suggest using a mapping from your system to the canonical polar coordinates.

canonical <- function(r, theta) {
  if (r >= 0) {
    c(r = r, theta = theta %% (2*pi))
  } else {
    c(r = -r, theta = (theta + pi) %% (2*pi))
  }
}

Or shorter and vectorised:

canonical <- function(r, theta) {
  list(r = abs(r), 
       theta = (theta + ifelse(r < 0, pi, 0)) %% (2 * pi))
}

This leaves valid polar coordinates untouched (except bringing theta in (0, 2pi) if it is not already) and converts points with r < 0 to valid polar coordinates.

canonical(1, 0)
# untouched 

canonical(-1, 0)
# becomes (1, pi)

The advantage is that you can use all the standard polar functions from ggplot after converting.

library(ggplot2)

df <- data.frame(r = c(-100, -50, 0, 50, 100) , theta = rep(1, 5))
df_polar <- as.data.frame(canonical(df$r, df$theta))

ggplot(df_polar,
       aes(x = r, y = theta)) +
  geom_text(aes(label = paste(round(r, 1),',', round(theta, 1)))) +
  coord_polar(theta = 'y') +
  scale_y_continuous(limits = c(0, 2*pi),
                     breaks = c(0, pi/2, pi, 3*pi/2 ),
                     labels = c('0', 'pi/2', 'pi', '3/2pi'))

Results with polar coordinates

Another option in the same vein is to convert from polar to cartesian coordinates to make it easy to draw straight lines. The mapping is x = r*cos(theta) and y=r*sin(theta) and, interestingly, is valid for negative r as well since cos(theta+pi) = -cos(theta) and same for sin.

asachet
  • 6,620
  • 2
  • 30
  • 74
  • One problem with this approach is I could not draw straight lines in polar coordinates, because of how negative `r` is plotted. The equation is plotted fine in other software that can plot in what - I would consider - a polar coordinate system. This is a link to wolfram where they plot negative r: http://mathworld.wolfram.com/PolarCoordinates.html – Dambo Jul 22 '19 at 17:10
  • Have you considered converting from polar to cartesian, where drawing lines with ggplot is easy? – asachet Jul 24 '19 at 06:55
  • Yes, but I really meant to be able to draw in polar coordinates. However, I looked up the Grammar of Graphics, which says "We could treat polar coordinates as an exception to the way all other scales are handled in this system. That is, we could interpret angular values absolutely as radians. This would make sense if all our graphics were mathematical or engineering applications involving radians. We have chosen not to do this, however, so that we can hide scaling details when doing coordinate conversions" (p.205) - so I guess a polar system is just not available in ggplot2 – Dambo Jul 25 '19 at 04:29