I am modifying this tutorial to create a circular calendar of a year. I am trying to subdivide the calendar into seasons, but because the geom_segment
for winter crosses zero degrees on my polar plot, the winter geom_segment
goes counter clockwise instead of clockwise from a starting point of 12 to an ending point of 2, intersecting the geom_segments
of the other seasons. I know that crossing zero is the issue because in my first pass I binned the seasons starting at 1, just to make the plot run, and the segments and labels didn't intersect.
Here's what the segments should look like, but I've removed winter because it's causing problems.
Here's what it looks like when I include winter, which intersects the other segments instead of crossing zero.
Here is my code:
library(ggplot2)
library(tidyverse)
library(viridis)
library(forcats)
library(data.table)
library(dplyr)
# Create dataset
data <- data.frame(
month=factor(c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")),
group=factor(c( rep('WI', 3), rep('SP', 3), rep('SU', 3), rep('FA', 3))) ,
value1=1.5,
value2=5,
value3=1.5,
value4=10,
value5=20,
value6=30
)
# Transform data in a tidy format (long format)
data <- data %>% gather(key = "observation", value="value", -c(1,2))
# Get the name and the y position of each label
label_data <- data %>% group_by(month = factor(month, levels = unique(month))) %>% summarize(tot=sum(value))
number_of_bar <- nrow(label_data)
label_data <- rownames_to_column(label_data)
names(label_data)[names(label_data) == "rowname"] <- "id"
label_data$id <- as.numeric(label_data$id)
angle <- 90 - 360 * (label_data$id-0.5) /number_of_bar # I substract 0.5 because the letter must have the angle of the center of the bars. Not extreme right(1) or extreme left (0)
label_data$hjust <- ifelse(angle < -90, 1, 0)
label_data$month <- c("J","F","M","A","M","J","J","A","S","O","N","D")
group <- c("WI","SP","SU","FA")
start <- c(12,3,6,9)
end <- c(2,5,8,11)
base_data <- data.frame(group,start,end)
base_data <- base_data %>%
mutate(title = (start + end)/2)
# base_data <- base_data[-1,] # adding this row removes the winter segment and text completely, leaving it in causes the problem
# prepare a data frame for grid (scales)
grid_data <- base_data
grid_data$end <- grid_data$end[ c( nrow(grid_data), 1:nrow(grid_data)-1)] + 1
grid_data$start <- grid_data$start - 1
grid_data <- grid_data[-1,]
p <- ggplot(data) +
# Add the stacked bar
geom_bar(aes(x=factor(month), y=value, fill=observation), stat="identity", alpha=0.5) +
scale_fill_viridis_d() +
ylim(-30,70) +
theme_minimal() +
theme(
legend.position = "none",
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-1,4), "cm")
) +
coord_polar() +
# Add labels on top of each bar
geom_text(data=label_data, aes(x=id, y=63.5, label=month, hjust=hjust), color="black", fontface="bold",alpha=0.6, size=4, inherit.aes = FALSE ) +
# Add base line information
geom_segment(data=base_data, aes(x = start, y = -5, xend = end, yend = -5), colour = "black", alpha=0.8, size=0.6 , inherit.aes = FALSE ) +
geom_text(data=base_data, aes(x = title, y = -10, label=group), colour = "black", alpha=0.8, size=4, fontface="bold", inherit.aes = FALSE)
p
One option to achieve your desired result would be to first draw a full circle, then add the gaps between the seasons using a second geom_segment
or geom_path
for which you set the color to "white".
Note: In the code below I use annotate
with geom="path"/"text"
to add the segments and the text.
library(ggplot2)
p <- ggplot(data) +
# Add the stacked bar
geom_bar(aes(x = factor(month), y = value, fill = observation),
stat = "identity", alpha = 0.5
) +
scale_fill_viridis_d() +
ylim(-30, 70) +
theme_minimal() +
theme(
legend.position = "none",
axis.text = element_blank(),
axis.title = element_blank(),
panel.grid = element_blank(),
plot.margin = unit(rep(-1, 4), "cm")
) +
# Add labels on top of each bar
geom_text(
data = label_data, aes(x = id, y = 63.5, label = month, hjust = hjust),
color = "black", fontface = "bold", alpha = 0.6, size = 4, inherit.aes = FALSE
) +
# Add base line information
annotate(
geom = "path",
x = c(.5, 12.5), y = -5,
color = "black", alpha = 0.8, linewidth = 0.6,
) +
annotate(
geom = "path",
x = c(2, 3, 5, 6, 8, 9, 11, 12), y = -5,
group = c(0, 0, 1, 1, 2, 2, 3, 3),
color = "white", linewidth = 1,
) +
annotate(
geom = "text",
x = c(1, 4, 7, 10), y = -12,
label = c("WI", "SP", "SU", "FA"),
alpha = 0.8, size = 4, fontface = "bold"
) +
coord_polar()
p