Reputation: 43
I am trying to make a radar plot with ggplot2. I have used the geom_polygon and coord_polar functions to create a closed and curved plot. The issue is that between the last and the first point, the line is not curved, contrary to the others. I wonder why this is the case and I would like to modify the line in order to make it curved.
I've looked at the coord_polar function but I did not find any solution...
Here is my code:
dput(vsg_emo_nbRC)
structure(list(variable = structure(c(2L, 3L, 4L, 5L, 6L, 2L,
3L, 4L, 5L, 6L), .Label = c("", "Neutre", "Colère", "Embarras",
"Fierté", "Surprise"), class = "factor"), Groupe = structure(c(1L,
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L), .Label = c("DS", "VS"), class = "factor"),
moy_DS = c(2.22, 3.11, 2.89, 3.33, 2.67, 3.36, 3.88, 3.48,
4, 3.6), std_err_DS = c(1.72, 1.17, 1.54, 1.12, 0.71, 0.95,
0.33, 0.65, 0, 0.71), IC_upper_DS = c(2.6, 3.37, 3.22, 3.58,
2.82, 3.43, 3.91, 3.53, 4, 3.66), IC_lower_DS = c(1.85, 2.86,
2.55, 3.09, 2.51, 3.29, 3.85, 3.43, 4, 3.54)), row.names = c(1L,
2L, 3L, 4L, 5L, 30L, 31L, 32L, 33L, 34L), class = "data.frame")
vsg_emo_nbRC %>%
ggplot(aes(x = variable, y = moy_DS, colour = Groupe, group = Groupe, linetype = Groupe)) +
geom_polygon(aes(y = IC_upper_DS), fill = "grey50", alpha = 0.2, linetype= "dotted") +
geom_polygon(aes(y = IC_lower_DS), fill = "grey99", alpha = 0.2, linetype="dotted") +
geom_polygon(fill = NA) +
theme_light() +
theme(panel.grid.minor = element_blank()) +
coord_polar() +
scale_colour_manual(values = c("#d8b365", "#5ab4ac")) +
scale_linetype_manual(values = c(1,1)) +
labs(x = "", y = "", title = "Performances moyennes de reconnaissance d'émotions dans la tâche visage") +
expand_limits(x=c(0,4), y=c(0,4)) +
geom_text(aes(label=moy_DS)) +
scale_y_continuous(limits = c(0,4))
Any help would be welcome ! Thanks a lot
Upvotes: 4
Views: 253
Reputation: 38003
The reason that coord_polar
doesn't handle this situation very well is because there is an invisible x-axis boundary between your first and last (Surprise & Neutre) x-position, for which there is not data to be curved around.
There is a solution to be build, but it would involve building a new geom so here we go. First, we'll build the function that we'll actually use:
geom_polarpoly <- function (mapping = NULL, data = NULL, stat = "identity",
position = "identity", rule = "evenodd", ...,
na.rm = FALSE, show.legend = NA, inherit.aes = TRUE)
{
layer(data = data, mapping = mapping, stat = stat, geom = GeomPolarPoly,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, rule = rule, ...))
}
This a near-identical function to geom_poly()
but, it sets the geom to the ggproto object that we'll build next:
GeomPolarPoly <- ggproto(
"GeomPolarPoly",
GeomPolygon,
draw_panel = function(data, panel_params, coord, rule = "evenodd", self) {
df <- split(data, data$group)
df <- lapply(df, function(dat) {
dummy <- rbind(head(dat, 1), tail(dat, 1))
dummy$x <- panel_params$theta.range
dummy$y <- mean(dummy$y)
rbind(dummy[1, ],
dat,
dummy[2, ])
})
data <- do.call(rbind, df)
ggproto_parent(GeomPolygon, self)$draw_panel(data = data,
panel_params = panel_params,
coord = coord,
rule = rule)
})
What this ggproto object does, is copy everything from GeomPolygon
with a modification to the panel drawing code. The difference with the original panel drawing code, is that it will now place two extra points at both the extremes of the x-axis and gives these both a y-value that is in between the first and last point of the original polygon.
Now that there is data to be curved, we can make a nice curved radial plot:
vsg_emo_nbRC %>%
ggplot(aes(x = variable, y = moy_DS, colour = Groupe, group = Groupe, linetype = Groupe)) +
geom_polarpoly(aes(y = IC_upper_DS), fill = "grey50", alpha = 0.2, linetype= "dotted") +
geom_polarpoly(aes(y = IC_lower_DS), fill = "grey99", alpha = 0.2, linetype="dotted") +
geom_polarpoly(fill = NA) +
theme_light() +
theme(panel.grid.minor = element_blank()) +
coord_polar() +
scale_colour_manual(values = c("#d8b365", "#5ab4ac")) +
scale_linetype_manual(values = c(1,1)) +
labs(x = "", y = "", title = "Performances moyennes de reconnaissance d'émotions dans la tâche visage") +
expand_limits(x=c(0,4), y=c(0,4)) +
geom_text(aes(label=moy_DS)) +
scale_y_continuous(limits = c(0,4))
Note that I haven't tested this geom extensively, but it seems to fit the bill for this question, and other questions like it.
Upvotes: 3