注释框跟随图例位置ggplot2

问题描述 投票:0回答:1

我的数据:

plot_data <- structure(list(date = structure(c(18993, 18994, 18995, 18996, 
18997, 18998, 18999, 19000, 19001, 19002, 19003, 19004, 19005, 
19006, 19007, 19008, 19009, 19010, 19011, 19012, 19013, 19014, 
19015, 19016, 19017, 19018, 19019, 19020, 19021, 19022, 19023, 
19024, 19025, 19026, 19027, 19028, 19029, 19030, 19031, 19032, 
19033, 19034, 19035, 19036, 19037, 19038, 19039, 19040, 19041, 
19042, 19043, 19044, 19045, 19046, 19047, 19048, 19049, 19050, 
19051, NA, 19052, 19053, 19054, 19055, 19056, 19057, 19058, 19059, 
19060, 19061, 19062, 19063, 19064, 19065, 19066, 19067, 19068, 
19069, 19070, 19071, 19072, 19073, 19074, 19075, 19076, 19077, 
19078, 19079, 19080, 19081, 19082, 19083, 19084, 19085, 19086, 
19087, 19088, 19089, 19090, 19091, 19092, 19093, 19094, 19095, 
19096, 19097, 19098, 19099, 19100, 19101, 19102, 19103, 19104, 
19105, 19106, 19107, 19108, 19109, 19110, 19111, 19112, 19113, 
19114, 19115, 19116, 19117, 19118, 19119, 19120, 19121, 19122, 
19123, 19124, 19125, 19126, 19127, 19128, 19129, 19130, 19131, 
19132, 19133, 19134, 19135, 19136, 19137, 19138, 19139, 19140, 
19141, 19142, 19143, 19144, 19145, 19146, 19147, 19148, 19149, 
19150, 19151, 19152, 19153, 19154, 19155, 19156, 19157, 19158, 
19159, 19160, 19161, 19162, 19163, 19164, 19165, 19166, 19167, 
19168, 19169, 19170, 19171, 19172, 19173, 19174, 19175, 19176, 
19177, 19178, 19179, 19180, 19181, 19182, 19183, 19184, 19185, 
19186, 19187, 19188, 19189, 19190, 19191, 19192, 19193, 19194, 
19195, 19196, 19197, 19198, 19199, 19200, 19201, 19202, 19203, 
19204, 19205, 19206, 19207, 19208, 19209, 19210, 19211, 19212, 
19213, 19214, 19215, 19216, 19217, 19218, 19219, 19220, 19221, 
19222, 19223, 19224, 19225, 19226, 19227, 19228, 19229, 19230, 
19231, 19232, 19233, 19234, 19235, 19236, 19237, 19238, 19239, 
19240, 19241, 19242, 19243, 19244, 19245, 19246, 19247, 19248, 
19249, 19250, 19251, 19252, 19253, 19254, 19255, 19256, 19257, 
19258, 19259, 19260, 19261, 19262, 19263, 19264, 19265, 19266, 
19267, 19268, 19269, 19270, 19271, 19272, 19273, 19274, 19275, 
19276, 19277, 19278, 19279, 19280, 19281, 19282, 19283, 19284, 
19285, 19286, 19287, 19288, 19289, 19290, 19291, 19292, 19293, 
19294, 19295, 19296, 19297, 19298, 19299, 19300, 19301, 19302, 
19303, 19304, 19305, 19306, 19307, 19308, 19309, 19310, 19311, 
19312, 19313, 19314, 19315, 19316, 19317, 19318, 19319, 19320, 
19321, 19322, 19323, 19324, 19325, 19326, 19327, 19328, 19329, 
19330, 19331, 19332, 19333, 19334, 19335, 19336, 19337, 19338, 
19339, 19340, 19341, 19342, 19343, 19344, 19345, 19346, 19347, 
19348, 19349, 19350, 19351, 19352, 19353, 19354, 19355, 19356, 
19357), class = "Date"), cumsumpcp = c(0, 0, 0, 7.3, 12.3, 12.3, 
12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 
12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 
12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 12.3, 
12.3, 12.3, 12.3, 12.3, 13.3, 13.3, 13.3, 13.3, 13.3, 13.3, 13.3, 
13.3, 13.3, 13.3, 13.3, 13.6, 17.5, 20.9, 21, 21, NA, 21, 21, 
39.2, 39.2, 39.2, 45.1, 47.9, 47.9, 47.9, 47.9, 47.9, 47.9, 47.9, 
NA, 47.9, 47.9, 48.1, 48.1, 48.1, 54.8, 80.2, 81.4, 83.2, 89.4, 
93.8, 93.8, 93.8, 93.8, 101.2, 102.2, 103, 103.1, 103.1, 103.1, 
103.1, 103.1, 103.1, 103.1, 103.1, 103.1, 103.1, 107.4, 111.5, 
111.5, 111.5, 111.5, 111.5, 111.5, 111.5, 126.8, 127.5, 128.8, 
151.6, 153.5, 153.6, 153.6, 162.5, 163.6, 165.7, 165.7, 165.7, 
165.7, 167.9, 170.5, 170.5, 170.5, 170.5, 170.5, 170.5, 170.5, 
170.5, 170.5, 170.5, 170.5, 171.3, 171.3, 171.3, 171.3, 171.3, 
171.3, 171.3, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 
171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 
171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 171.9, 
171.9, 172, 172, 172, 172, 172, 172, 172.2, 172.2, 172.2, 172.2, 
172.2, 172.2, 172.2, 172.2, 172.2, 172.2, 172.2, 172.2, 172.2, 
172.2, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 
180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 
180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 180.4, 182, 182, 182, 
182.8, 182.8, 184.8, 184.8, 184.8, 184.8, 184.8, 184.8, 184.8, 
184.8, 184.8, 184.8, 184.8, 184.8, 184.8, 186.9, 186.9, 186.9, 
186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 
186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 186.9, 
186.9, 186.9, 186.9, 186.9, 187.2, 205.7, 206.3, 206.5, 221, 
221, 221, 221, 228, 228, 228, 228, 228, 228, 228, 228, 228, 228, 
230.7, 230.8, 230.8, 230.8, 230.8, 230.8, 230.8, 230.8, 230.8, 
230.8, 231.4, 235.1, 235.1, 235.1, 235.1, 235.1, 235.1, 236.9, 
237, 237, 237.4, 246.2, 249.7, 255.4, 257.2, 257.2, 257.2, 257.2, 
257.2, 257.2, 257.2, 257.2, 258.6, 258.6, 258.6, 258.6, 258.6, 
258.6, 258.6, 258.6, 260.8, 266.2, 266.3, 268.4, 270.9, 270.9, 
271.5, 277.9, 281.6, 281.7, 281.9, 281.9, 281.9, 289.7, 292.1, 
292.2, 298.5, 298.5, 298.5, 303.9, 304, 304, 304, 304, 304, 305.8, 
307.3, 320.4, 320.4, 322.8, 340.5, 350.9, 359.4, 363.5, 383, 
409.1, 435.7, 436, 438, 438, 438, 438, 449, 449, 449.3, 449.4, 
449.4, 449.4, 449.4, 449.4, 449.4, 449.4, 449.4, 449.4)), row.names = c(NA, 
-366L), class = c("tbl_df", "tbl", "data.frame"))

ranking_max_consec_days_no_pcp <- structure(list(year = c("2023", "1924", "1985", "1930", "1921", 
"1939", "1962", "1937", "1988", "1965", "2016", "1970", "1998", 
"1978", "1922", "1997", "2000", "2018", "1984", "1980", "2014", 
"1967", "1926", "1973", "1954", "2011", "1974", "1946", "1949", 
"1953", "2017", "1932", "1944", "1942", "1960", "2007", "1934", 
"1935", "1936", "1957", "1994", "1979", "1964", "1982", "2012", 
"1931", "1975", "1995", "1945", "1963", "1986", "1983", "2022", 
"1923", "1966", "2002", "1933", "1972", "2015", "1920", "1968", 
"1969", "1989", "2003", "2009", "2010", "1941", "1991", "2001", 
"2005", "1948", "1992", "2020", "1958", "1990", "2004", "2019", 
"1940", "1952", "1981", "1993", "2008", "2021", "1951", "2013", 
"1929", "2006", "1925", "1955", "1976", "1977", "1996", "1947", 
"1950", "1971", "1999", "1927", "1961", "1959", "1943", "1956", 
"1987"), consecdaysnopcp = c(160L, 106L, 101L, 98L, 97L, 87L, 
85L, 84L, 82L, 70L, 67L, 66L, 66L, 64L, 63L, 63L, 63L, 63L, 62L, 
61L, 60L, 57L, 56L, 55L, 53L, 53L, 50L, 49L, 49L, 49L, 49L, 48L, 
46L, 45L, 45L, 44L, 43L, 43L, 43L, 43L, 43L, 42L, 41L, 41L, 41L, 
40L, 40L, 40L, 39L, 39L, 39L, 38L, 38L, 37L, 37L, 37L, 36L, 36L, 
36L, 35L, 35L, 35L, 35L, 35L, 35L, 35L, 34L, 34L, 34L, 34L, 33L, 
33L, 33L, 32L, 32L, 32L, 32L, 31L, 31L, 31L, 31L, 31L, 31L, 29L, 
29L, 28L, 28L, 27L, 27L, 27L, 27L, 27L, 26L, 26L, 25L, 24L, 23L, 
23L, 22L, 21L, 21L, 20L), ranking = 1:102), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -102L))

ranking_max_consec_days_pcp <- structure(list(year = c("2018", "1970", "1971", "1946", "2010", 
"1960", "1966", "1958", "1972", "1989", "1993", "1999", "2009", 
"1936", "1947", "1955", "1956", "1963", "1974", "1979", "1995", 
"1998", "2007", "1921", "1937", "1951", "1961", "1969", "1975", 
"1976", "1978", "1980", "2021", "2022", "1923", "1925", "1926", 
"1927", "1931", "1935", "1941", "1977", "1984", "1986", "1988", 
"1996", "1997", "2016", "1922", "1932", "1933", "1939", "1942", 
"1948", "1952", "1953", "1964", "1965", "1983", "2001", "2004", 
"2011", "2013", "2020", "1924", "1930", "1934", "1943", "1957", 
"1959", "1962", "1967", "1973", "1982", "1987", "1992", "1994", 
"2000", "2002", "2006", "2012", "2014", "1920", "1940", "1949", 
"1954", "1968", "1981", "1985", "1990", "1991", "2003", "2015", 
"2017", "2019", "2023", "1944", "1950", "2008", "1929", "1945", 
"2005"), consecdayspcp = c(19L, 17L, 16L, 14L, 14L, 13L, 13L, 
12L, 12L, 12L, 12L, 12L, 12L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 
11L, 11L, 11L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 9L, 
8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 
7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 
7L, 7L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 
5L, 5L, 5L, 4L, 4L, 4L), ranking = 1:102), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -102L))

我的代码:

selected_year <- 2022    
ggplot2::ggplot(data = plot_data, aes(x = date, y = cumsumpcp)) +
      ggplot2::geom_line(aes(color = "cumsumpcp"), linewidth = 0.85, lineend = "round", na.rm = TRUE) +
      ggplot2::scale_color_manual(values = c("cumsumpcp" = "black"), 
                                  label = paste0("Cumulative daily precip. (2022)")) +
      ggplot2::scale_x_continuous(
        breaks = as.numeric(seq(ymd(paste0(selected_year, "-01-01")), ymd(paste0(selected_year, "-12-31")), by = "month")),
        labels = c("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"),
        limits = c(as.numeric(ymd(paste0(selected_year, "-01-01"))), 
                   as.numeric(ymd(paste0(as.numeric(selected_year) + 1, "-02-04")))),
        expand = expansion(mult = c(0.02, 0))
      ) +
      ggplot2::scale_y_continuous(
        labels = function(x) paste0(x, "mm"),
        breaks = seq(from = 0, to = max(plot_data$cumsumpcp, na.rm = TRUE) + 200, by = 100),
        limits = c(0, max(plot_data$cumsumpcp, na.rm = TRUE) + 200),
        expand = c(0, 20, 0, 0)
      ) +
      ggplot2::annotate(
        geom = "richtext", x = min(plot_data$date, na.rm = TRUE) + 25, 
        y = max(plot_data$cumsumpcp, na.rm = TRUE) - 100, 
        label = paste0("**Ranking** (", 1920, "-", 2023, ")<br>", 
                       "Max consecutive days with precip. <br><br>", 
                       head(ranking_max_consec_days_pcp, 1)$ranking, "º ", 
                       head(ranking_max_consec_days_pcp, 1)$year, ": ", 
                       head(ranking_max_consec_days_pcp, 1)$consecdayspcp, " days<br>",
                       head(ranking_max_consec_days_pcp, 2)[2,]$ranking, "º ", 
                       head(ranking_max_consec_days_pcp, 2)[2,]$year, ": ", 
                       head(ranking_max_consec_days_pcp, 2)[2,]$consecdayspcp, " days<br>",
                       head(ranking_max_consec_days_pcp, 3)[3,]$ranking, "º ",
                       head(ranking_max_consec_days_pcp, 3)[3,]$year, ": ", 
                       head(ranking_max_consec_days_pcp, 3)[3,]$consecdayspcp, " days<br>",
                       "---------------------------<br>",
                       subset(ranking_max_consec_days_pcp, 
                              ranking_max_consec_days_pcp$year == selected_year)$ranking, "º ",
                       selected_year, ": ",
                       subset(ranking_max_consec_days_pcp, 
                              ranking_max_consec_days_pcp$year == selected_year)$consecdayspcp,
                       " days"), 
        hjust = 0, vjust = 0.5, label.size = 0.75, label.padding = unit(0.5, "lines")
      ) + 
      ggplot2::annotate(
        geom = "richtext", x = min(plot_data$date, na.rm = TRUE) + 95, 
        y = max(plot_data$cumsumpcp, na.rm = TRUE) - 15, 
        label = paste0("**Ranking** (", 1920, "-", 2023, ")<br>", 
                       "Max consecutive days with no precip. <br><br>", 
                       head(ranking_max_consec_days_no_pcp, 1)$ranking, "º ", 
                       head(ranking_max_consec_days_no_pcp, 1)$year, ": ", 
                       head(ranking_max_consec_days_no_pcp, 1)$consecdaysnopcp, " days<br>",
                       head(ranking_max_consec_days_no_pcp, 2)[2,]$ranking, "º ", 
                       head(ranking_max_consec_days_no_pcp, 2)[2,]$year, ": ", 
                       head(ranking_max_consec_days_no_pcp, 2)[2,]$consecdaysnopcp, " days<br>",
                       head(ranking_max_consec_days_no_pcp, 3)[3,]$ranking, "º ",
                       head(ranking_max_consec_days_no_pcp, 3)[3,]$year, ": ", 
                       head(ranking_max_consec_days_no_pcp, 3)[3,]$consecdaysnopcp, " days<br>",
                       "---------------------------<br>",
                       subset(ranking_max_consec_days_no_pcp, 
                              ranking_max_consec_days_no_pcp$year == selected_year)$ranking, "º ",
                       selected_year, ": ",
                       subset(ranking_max_consec_days_no_pcp, 
                              ranking_max_consec_days_no_pcp$year == selected_year)$consecdaysnopcp,
                       " days"), 
        hjust = 0, vjust = 0.5, label.size = 0.75, label.padding = unit(0.5, "lines")
      ) +
      ggthemes::theme_hc(base_size = 15) +
      ggplot2::theme(
        plot.title = ggplot2::element_text(hjust = 1, face = "bold", family = "sans", size = 35),
        plot.subtitle = ggplot2::element_text(hjust = 1, size = 25),
        legend.background = ggplot2::element_blank(),
        legend.box.background = ggplot2::element_rect(fill = "white", color = "black", linewidth = 0.75),
        legend.position = c(0.125, 0.85),
        legend.spacing = ggplot2::unit(0, "cm"),
        legend.margin = ggplot2::margin(r = 5, l = 5, b = 5),
        legend.title = ggplot2::element_blank())

输出:

如您所见,我使用

legend.position = c(0.125, 0.85)
定义了图例位置,并使用
annotate
(日期)和
x
(cumsumpcp)值定义了我的
y
框,但它们距离图例框非常远。我希望注释框自动出现在图例框旁边。有没有办法做到这一点?有没有办法设置与
legend.position
相同单位的注释框?

r ggplot2 legend annotate
1个回答
0
投票

如果您以相对单位而不是绝对数据坐标定位某些内容,那么

annotation_custom
始终是一个比
annotate
处理 grobs 稍微高级的选项。但正如您所看到的,这是值得的,因为它允许将 x/y 位置与图例框完美对齐。除了切换到
annotation_custom
之外,我还在
legend.justification
中设置了
theme
,在将图例放置在面板内时,您应该始终这样做。此外,我通过使用函数创建标签来简化了您的代码。最后注意
gridtext
包的使用,它提供了底层的 grobs
ggtext

library(ggplot2)
library(gridtext)
library(lubridate)

selected_year <- 2022

make_annotation <- function(x, col) {
  paste0(
    "**Ranking** (", 1920, "-", 2023, ")<br>",
    "Max consecutive days with precip. <br><br>",
    head(x, 1)$ranking, "º ",
    head(x, 1)$year, ": ",
    head(x, 1)[[col]], " days<br>",
    head(x, 2)[2, ]$ranking, "º ",
    head(x, 2)[2, ]$year, ": ",
    head(x, 2)[2, col], " days<br>",
    head(x, 3)[3, ]$ranking, "º ",
    head(x, 3)[3, ]$year, ": ",
    head(x, 3)[3, col], " days<br>",
    "---------------------------<br>",
    subset(
      x,
      x$year == selected_year,
      select = ranking
    ), "º ",
    selected_year, ": ",
    subset(
      x,
      x$year == selected_year,
      select = col
    ),
    " days"
  )
}

ggplot(data = plot_data, aes(x = date, y = cumsumpcp)) +
  geom_line(aes(color = "cumsumpcp"),
    linewidth = 0.85,
    lineend = "round", na.rm = TRUE
  ) +
  scale_color_manual(
    values = c("cumsumpcp" = "black"),
    label = paste0("Cumulative daily precip. (2022)")
  ) +
  scale_x_continuous(
    breaks = as.numeric(
      seq(ymd(paste0(selected_year, "-01-01")),
        ymd(paste0(selected_year, "-12-31")),
        by = "month"
      )
    ),
    labels = month.abb,
    limits = c(
      as.numeric(ymd(paste0(selected_year, "-01-01"))),
      as.numeric(ymd(paste0(as.numeric(selected_year) + 1, "-02-04")))
    ),
    expand = expansion(mult = c(0.02, 0))
  ) +
  # scale_y_continuous(
  #   labels = function(x) paste0(x, "mm"),
  #   breaks = seq(from = 0, to = max(plot_data$cumsumpcp) + 200, by = 100),
  #   limits = c(0, max(plot_data$cump100pcp) + 200),
  #   expand = c(0, 20, 0, 0)
  # ) +
  annotation_custom(
    gridtext::richtext_grob(
      x = unit(.05, "npc"),
      y = unit(.8, "npc"),
      text = make_annotation(ranking_max_consec_days_pcp, "consecdayspcp"),
      hjust = 0, vjust = 1, 
      r = unit(0.15, "lines"),
      box_gp = grid::gpar(col = "black", lwd = 2),
      padding = unit(0.5, "lines")
    )
  ) +
  annotation_custom(
    gridtext::richtext_grob(
      x = unit(.4, "npc"),
      y = unit(.95, "npc"),
      text = make_annotation(ranking_max_consec_days_no_pcp, "consecdaysnopcp"),
      hjust = 0, vjust = 1, 
      r = unit(0.15, "lines"),
      box_gp = grid::gpar(col = "black", lwd = 2),
      padding = unit(0.5, "lines")
    )
  ) +
  ggthemes::theme_hc(base_size = 15) +
  theme(
    plot.title = element_text(
      hjust = 1, face = "bold", family = "sans", size = 35
    ),
    plot.subtitle = element_text(hjust = 1, size = 25),
    legend.background = element_blank(),
    legend.box.background = element_rect(
      fill = "white", color = "black", linewidth = 0.75
    ),
    legend.position = c(0.05, .95),
    legend.justification = c(0, 1),
    legend.spacing = unit(0, "cm"),
    legend.margin = margin(r = 5, l = 5, b = 5),
    legend.title = element_blank()
  )

# ggsave("foo.png", width = 800, height = 600, units = "px", scale = 4)

© www.soinside.com 2019 - 2024. All rights reserved.