问题
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)
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")
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")
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")
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")
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.
回答1:
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()
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.
来源:https://stackoverflow.com/questions/47760020/how-to-wrap-around-the-polar-coordinate-limits-in-ggplot2