我可以想到两种方法来做到这一点,每种方法都有其优点和缺点:
数据准备:
library(dplyr)
library(tibble)
library(lubridate)
library(scales)
library(ggplot2)
set.seed(122)
df <- as_tibble(rlnorm(1260, meanlog = 0.06, sdlog = 0.20))
df$month <- rep(month.abb, 5, each=21)
df$year <- rep(c("Year 1", "Year 2", "Year 3", "Year 4", "Year 5"), 1, each=252)
# We first create a "real" date variable with year, month and day. I've chosen to add
# "201" in from of your year, but it really doesn't matter in our case.
df <- df %>%
group_by(year, month) %>%
mutate(Date = as.Date(paste0("201", sub("^.+(\\d+)$", "\\1", year),
"-", month, "-", row_number()),
format = "%Y-%b-%d"))
# Since OP's daily values don't make up full months of data,
# we need this step to show missing data correctly.
df <- expand.grid(Date = seq.Date(from = min(df$Date), to = max(df$Date), by = "days")) %>%
mutate(year = paste("Year", sub("^\\d{3}(\\d)", "\\1", format(Date, "%Y"))),
month = format(Date, "%b")) %>%
left_join(df)
请注意,我已经使用了month.abb
替换 OP 提供的月份,因为看起来他们使用的是非英语语言环境。
1. Use facet_grid
:
ggplot(df, aes(x = Date, y = value, group = year)) +
geom_line() +
facet_grid(. ~ year, scale = "free_x") +
scale_x_date(labels = date_format("%b"), expand = c(0, 0)) +
theme(panel.spacing.x = unit(0, "lines")) +
ylim(c(0, 2.5))
我用过expand
in scale_x_date
防止 ggplot 在每个面的两端添加空格panel.spacing.x
以减少刻面之间的间距。这两者的组合给我们一种错觉,即面板已连接,但实际上并非如此(即使没有缺失值,每个面的末尾也不会连接到下一个面的开头)
2. Use geom_rect
+ geom_text
:
# Create labels
label_range <- df %>%
group_by(year) %>%
summarize(xmin = min(Date),
xmax = max(Date),
ymin = -0.5,
ymax = ymin + 0.15)
ggplot(df) +
geom_line(aes(x = Date, y = value)) +
geom_rect(data = label_range, fill = "lightcoral", color = "#f2f2f2",
aes(xmin = xmin, xmax = xmax,
ymin = ymin, ymax = ymax,
group = year)) +
geom_text(data = label_range,
aes(x = xmin + 365/2, y = ymin + 0.1,
group = year, label = year)) +
coord_cartesian(ylim = c(0, 2.5), clip = "off") +
scale_x_date(labels = date_format("%b"),
date_breaks = "1 month",
expand = c(0.01, 0.01)) +
theme_bw() +
theme(plot.margin = unit(c(1,1,3,1), "lines"))
第二种方法比较繁琐,但我们的数据将被视为一个连续的系列。
Create label_range
确定每个的四个角的坐标geom_rect
.
使用这个数据集,我使用以下方法绘制了“构面框”geom_rect
和他们的标签使用geom_text
分组依据year
.
我们希望矩形位于 x 轴下方,所以我使用了coord_cartesian
将绘图设置为特定缩放,这可以防止当我们将其设置在绘图之外时,矩形被剪掉。
plot.margin
在 x 轴下方为构面标签添加一些空格
注意之间的差距Dec
and Jan
。它们是由缺失值引起的,这与之间的差距不同Dec
and Jan
在第一种方法中。