提问人:Ahsk 提问时间:9/24/2023 最后编辑:M--Ahsk 更新时间:9/27/2023 访问量:116
如何在 ggplot2 中对齐不同年份的周数?
How to align weeks in different years in ggplot2?
问:
如何在 x 轴上对齐不同年份的周数,以便对齐同一月份(如 6 月)的周数?
请注意,数据不是在不同年份的同一周内收集的,因此有些周无法对齐,这没关系。我只想对齐不同年份相同月份发生的周数,以比较不同年份不同周数的时间模式。
这是我的代码:
p <- ggplot(df, aes(x = date_in, y = total_count, fill = Treatment)) +
geom_col() +
facet_grid(year ~ .) + # Stacking years on top of each other
theme_few(base_size = 10, base_family = "Arial") +
theme(axis.text.x = element_text(angle = 90, hjust = 1,
vjust = 0.5, color = "black"),
axis.text.y = element_text(vjust = 0.5, color = "black"),
axis.title = element_text(color = "black"),
strip.text = element_text(face = "bold", color = "black")) +
facet_wrap(~ year, ncol = 1, scales = "free",
strip.position = "right") + # Righty-axis
theme(legend.position = "top") +
scale_fill_manual(values = c("IP" = "blue", "LD" = "red")) # Set custom colors
# Print the plot
print(p)
以下是可重现的示例数据集:
df <- structure(list(date_in = structure(c(7L, 11L, 11L, 13L, 13L,
15L, 15L, 18L, 18L, 21L, 5L, 5L, 7L, 7L, 9L, 9L, 11L, 11L, 13L,
13L, 17L, 17L, 20L, 20L, 23L, 23L, 26L, 26L, 28L, 28L, 1L, 1L,
2L, 2L, 3L, 3L, 4L, 4L, 6L, 6L), levels = c("03/08", "04/05",
"04/26", "05/17", "05/19", "05/24", "05/26", "05/31", "06/02",
"06/07", "06/09", "06/14", "06/16", "06/21", "06/23", "06/28",
"06/29", "06/30", "07/05", "07/06", "07/07", "07/12", "07/13",
"07/14", "07/19", "07/21", "07/26", "07/28", "08/02", "08/04",
"08/09", "08/11", "08/16", "08/17", "08/24", "08/25", "08/31",
"09/01", "09/07", "09/08", "09/14", "09/15", "09/21", "09/22",
"09/23", "09/28", "09/29", "09/30", "10/05", "10/06", "10/07",
"10/12", "10/13", "10/14", "10/19", "10/20", "10/21", "10/26",
"10/27", "10/29", "11/02", "11/03", "11/04", "11/09", "11/11",
"11/17", "11/23", "12/01", "12/07"), class = "factor"), total_count = c(0L,
0L, 0L, 0L, 4L, 3L, 13L, 0L, 0L, 16L, 2L, 2L, 18L, 362L, 135L,
684L, 34L, 123L, 6L, 21L, 2L, 4L, 6L, 6L, 1L, 11L, 0L, 12L, 1L,
2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 11L, 0L, 0L), Treatment = structure(c(2L,
2L, 4L, 2L, 4L, 2L, 4L, 2L, 4L, 2L, 2L, 4L, 2L, 4L, 2L, 4L, 2L,
4L, 4L, 2L, 4L, 2L, 2L, 4L, 4L, 2L, 4L, 2L, 2L, 4L, 2L, 4L, 2L,
4L, 2L, 4L, 2L, 4L, 2L, 4L), levels = c("between_row", "IP",
"mulch", "LD"), class = "factor"), year = structure(c(1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L,
4L, 4L, 4L, 4L, 4L, 4L), levels = c("2010", "2011", "2012", "2013"
), class = "factor")), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -40L))
我想要的输出如下所示
答:
1赞
Andy Baxter
9/24/2023
#1
这也许是一种使用 .从本质上讲,将每个以休息时间作为周数绘制,并重新应用开始周日期作为标签,以便图对齐:patchwork
library(tidyverse)
library(ggthemes)
dates_weeks <- df |>
mutate(date = mdy(paste0(date_in, year)),
week = week(date))
min_week <- min(dates_weeks$week)
max_week <- max(dates_weeks$week)
year_breaks <- 2010:2013 |>
set_names() |>
map(\(year_n) {
year_dat <- dates_weeks |>
filter(year == year_n) |>
select(date_in, week) |>
unique()
week_map <- character(max_week - min_week + 1)
names(week_map) <- seq(min_week, max_week)
week_map[as.character(year_dat$week)] <- as.character(year_dat$date_in)
week_map
})
library(patchwork)
dates_weeks |>
mutate(week = factor(week), Treatment = factor(Treatment)) |>
nest(data = -year) |>
mutate(pl = map2(data, year, \(data, year) {
# browser()
ggplot(data, aes(x = week, y = total_count, fill = Treatment)) +
geom_col() +
scale_x_discrete(
labels = year_breaks[[as.character(year)]],
drop = FALSE
) +
facet_wrap(year, strip.position = "right") +
scale_fill_manual(values = c("IP" = "blue", "LD" = "red"), drop = FALSE) +
theme_few(base_size = 10)
})) |>
pull(pl) |>
wrap_plots(ncol = 1) +
plot_layout(guides = "collect") &
theme(
legend.position = "top",
axis.text.x = element_text(
angle = 90,
hjust = 1,
vjust = 0.5,
color = "black"
),
axis.text.y = element_text(vjust = 0.5, color = "black"),
axis.title = element_text(color = "black"),
strip.text = element_text(face = "bold", color = "black")
)
评论
0赞
Andy Baxter
9/25/2023
编辑后的代码看起来如何?首先过滤掉 0 个观察周。
0赞
Andy Baxter
9/25/2023
哦,我明白!您的意思是,在计数为零的几周内,您期望该图表上有一个空条,但其他图表的同一周下方没有标签?所以应该出现在最低的图表上,但在它们上方应该是没有标签的空白区域?03/08
04/05
0赞
Andy Baxter
9/25/2023
上面的代码怎么样?我为每个方面提供了一组唯一的命名值作为周间休息时间,以排列跨年份的周数。上图中的关键是,即使日期不同,它也会将 和 作为同一周和同一周。我认为你想要的是什么,而其他方法正在努力管理?2010/07/07
2012/07/06
2011/05/19
2013/05/17
0赞
Andy Baxter
9/25/2023
对不起,忘记取出过滤语句。已在上面更新 - 目前每年每周都排队。我想的最后一个问题是,在顶部图中应该与第二张图(一年中的同一周)或在第二张图和第三张图中(每年所有第一个六月的观测值)对齐?06/09
06/09
06/02
06/29
1赞
M--
9/24/2023
#2
更新:
如果您需要根据日期编号对齐日期,那么我们需要获取周数并将其用于 .ggplot
我不知道有一种方法可以在分面中拥有自定义轴刻度标签,所以我只使用了轴上的周数并为实际日期添加了标签。不过,您可以创建多个绘图并将它们拼接在一起。
library(dplyr)
library(tidyr)
library(ggplot2)
library(ggthemes)
df %>%
mutate(across(where(is.factor), as.character),
week_no = strftime(paste(year, date_in, sep = "/"), format = "%V")) %>%
filter(total_count != 0) %>%
pivot_wider(id_cols = c(week_no, year, date_in),
names_from = c(Treatment), values_from = c(total_count)) %>%
full_join(expand.grid(week_no = unique(.$week_no), year = unique(.$year)), .) %>%
replace_na(., list(date_in = "", LD = 0, IP = 0)) %>%
pivot_longer(LD:IP, names_to = "Treatment", values_to = "total_count") %>%
mutate(date_in = ifelse(Treatment == "IP", date_in, "")) %>%
ggplot(., aes(x = week_no, y = total_count, fill = Treatment)) +
geom_col() +
geom_text(aes(y=0, label=date_in), vjust=-0.5, color = "darkgray") +
facet_wrap(~ year, ncol = 1, scales = "free_y", strip.position = "right") +
scale_fill_manual(values = c("IP" = "navyblue", "LD" = "darkred")) +
xlab("Week no.") + ylab("Total Count") +
theme_few(base_size = 10, base_family = "Arial") +
theme(axis.text.x = element_text(angle = 90, hjust = 1,
vjust = 0.5, color = "black"),
axis.ticks.x = element_blank(),
axis.text.y = element_text(vjust = 0.5, color = "black"),
strip.text = element_text(face = "bold", color = "black"),
legend.position = "top")
创建于 2023-09-25 使用 reprex v2.0.2
原文答案:
您可以过滤掉空行,并仅显示具有 .free_x
date_in
total_count
library(ggplot2)
library(ggthemes)
ggplot(df[df$total_count != 0,], aes(x = date_in, y = total_count,
fill = Treatment)) +
geom_col() +
facet_wrap(~ year, ncol = 1, scales = "free_y", strip.position = "right") +
scale_fill_manual(values = c("IP" = "blue", "LD" = "red")) +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5,
color = "black"),
axis.text.y = element_text(vjust = 0.5, color = "black"),
axis.title = element_text(color = "black"),
strip.text = element_text(face = "bold", color = "black"),
legend.position = "top") +
theme_few(base_size = 10, base_family = "Arial")
创建于 2023-09-23 使用 reprex v2.0.2
评论