Reputation: 31
I have the following common scenario: I have climate data observations and predicitons for a certain point. To evaluate the model performance the data gets plotted in a line plot and the metrics should get display in the color of the respective line as text.
The resulting plot contains basically all the elements I need, but the geom_text() displays the labels not readable over each other. On the left side the values are the same for both predictions, so that only one text is visible, but they also lay over each other. The problem I have can be clearly seen in the two plots on the right side.
How can I adjust this? I tried using geom_text_repel() (resulted in missing labels) and using geom_text() in a loop with diferent y and x for geom_text() until now. Any help appreciated!
Here the data:
Data prepared for plotting:
structure(list(time = structure(c(1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400, 1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400, 1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400, 1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400, 1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400, 1506826800, 1506826800, 1509505200, 1509505200, 1512097200, 1512097200, 1514775600, 1514775600, 1517454000, 1517454000, 1519873200, 1519873200, 1522551600, 1522551600, 1525143600, 1525143600, 1527822000, 1527822000, 1530414000, 1530414000, 1533092400, 1533092400), tzone = "", class = c("POSIXct", "POSIXt")), Source = c("Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "Pred1 (wmo correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation", "Observation"), Station = c("PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG3", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4", "PG4"), variable = c("temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip", "temp", "precip"), value = c(288.84334108871, 43.0802236032481, 283.292141125, 50.5762518752008, 278.912795685484, 63.3694839260056, 280.065486854839, 46.944432518432, 276.980215044643, 47.0325918649175, 278.967870120968, 412.167444639785, 282.627421083333, 78.7950463642617, 284.651787217742, 43.4694896443769, 290.522796125, 0.7037754037678, 295.152023306452, 0, 295.091175080645, 4.430099105969, 285.346147016129, 55.577232932, 279.793625208333, 105.825640333, 275.887160080645, 166.87525632, 276.4884575, 81.029784211, 273.029221741071, 107.1414037242, 274.487727258065, 846.184536217, 278.949141125, 276.734242477, 280.430190080645, 35.5217026375, 286.738608583333, 4.42854513, 291.796912903226, 0, 290.786353104839, 26.342758098, 288.84334108871, 44.388101819812, 283.292141125, 52.6243076692389, 278.912795685484, 67.5961305373254, 280.065486854839, 36.5236296409472, 276.980215044643, 44.4754013996746, 278.967870120968, 404.50496651409, 282.627421083333, 84.5780219188797, 284.651787217742, 44.4483895406191, 290.522796125, 0.7227845871322, 295.152023306452, 0, 295.091175080645, 4.495902437649, 285.346147016129, 58.195027213, 279.793625208333, 113.797342811, 275.887160080645, 115.585107734, 276.4884575, 63.46318425, 273.029221741071, 80.4906799595, 274.487727258065, 622.595713923, 278.949141125, 173.082884898, 280.430190080645, 35.560077788, 286.738608583333, 4.61449558, 291.796912903226, 0, 290.786353104839, 26.804723069, 288.891370967742, 43, 283.278972222222, 50.4, 278.910860215054, 63, 280.0725, 33.1, 277.009821428571, 41.8, 279.003400537634, 374.3, 282.647625, 78.4, 284.692096774194, 43.4, 290.523208333333, 0.7, 295.408503184713, 0, 295.108611859838, 4.4, 285.241424731183, 55.83, 279.781638888889, 105.44, 275.904099462366, 83.63, 276.487594086021, 44.66, 272.997767857143, 55.07, 274.421733870968, 428.71, 278.796694444444, 86.12, 280.341102150538, 34.73, 286.669777777778, 4.44, 291.753897849462, 0, 290.652884097035, 26.41), id = c("1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", "2", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), RSquared = c(1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.998, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 0.957, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), NSE = c(1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, 0.985, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, -0.565, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.991, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, 1, 0.666, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), PBIAS = c(0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 7.9, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 84.4, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 7.1, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, 0, 39.9, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -132L))
Labels prepared for plotting:
structure(list(Source = c("Observation", "Observation", "Observation",
"Observation", "Pred1 (wmo correction)", "Pred1 (wmo correction)",
"Pred1 (wmo correction)", "Pred1 (wmo correction)", "pred2 (Kochendorfer correction)",
"pred2 (Kochendorfer correction)", "pred2 (Kochendorfer correction)",
"pred2 (Kochendorfer correction)"), Station = c("PG3", "PG3",
"PG4", "PG4", "PG3", "PG3", "PG4", "PG4", "PG3", "PG3", "PG4",
"PG4"), variable = c("precip", "temp", "precip", "temp", "precip",
"temp", "precip", "temp", "precip", "temp", "precip", "temp"),
RSquared = c(NA, NA, NA, NA, 0.998, 1, 0.957, 1, 1, 1, 0.985,
1), NSE = c(NA, NA, NA, NA, 0.985, 1, -0.565, 1, 0.991, 1,
0.666, 1), PBIAS = c(NA, NA, NA, NA, 7.9, 0, 84.4, 0, 7.1,
0, 39.9, 0)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA,
-12L))
Function to obtain labels for each variable:
get_labels <- function(var) {
labels <- list()
if (var == "temp") {
labels$y <- "Temperatur in K"
labels$title <- "Temperatur"
} else if (var == "precip") {
labels$y <- "Niederschlag in mm"
labels$title <- "Niederschlag"
} else if (var == "wind_speed") {
labels$y <- "Windgeschwindigkeit in m/s"
labels$title <- "Windgeschwindigkeit"
} else if (var == "rel_hum") {
labels$y <- "Relative Luftfeuchte in %"
labels$title <- "Relative Luftfeuchte"
}
return(labels)
}
Here the code to create the plot:
final_plots <- list()
for (var in variables) {
filtered_data <- filter(plot_data, variable == var)
filtered_label <- filter(label_data, variable == var & Source != "Observation")
labels <- get_labels(var)
p <- ggplot(data = filtered_data, aes(x = time, y = value, color = Source)) +
geom_line() +
geom_text_repel(data = filtered_label, aes(label = paste0("R²:", round(RSquared, 2), ", NSE:", round(NSE, 2), ", PBIAS:", round(PBIAS, 2)), x = min(filtered_data$time), y = Inf,color = Source), size = 2,hjust = -0.1, vjust = 1,show.legend = FALSE) +
facet_grid(Station ~ ., scales = "free_y") +
labs(
title = labels$title,
x = "Zeit",
y = labels$y,
color = "Data Source"
) +
theme_minimal() +
scale_color_brewer(palette = "Set1") +
scale_x_datetime(labels = function(x) format(x, "%b %Y"), breaks = "2 month") +
guides(color = guide_legend(title = "")) +
theme(
legend.position = "bottom",
panel.border = element_rect(color = "black", fill = NA, size = 0.4),
panel.grid.major = element_line(linetype = "dashed"),
panel.grid.minor = element_line(linetype = "dashed")
)
final_plots[[var]] <- p
}
Upvotes: 0
Views: 38
Reputation: 124268
Instead of using geom_text_repel
to add your labels one option to achieve your desired result would be to use a geom_text
or geom_label
where I use vjust
to vertically align one label at the top and one at the bottom.
library(dplyr, warn = FALSE)
library(ggrepel)
#> Loading required package: ggplot2
library(ggplot2)
variables <- c("temp", "precip")
plot_fun <- function(var) {
filtered_data <- filter(plot_data, variable == var)
filtered_label <- filter(label_data, variable == var, Source != "Observation")
labels <- get_labels(var)
filtered_label <- filtered_label |>
left_join(
filtered_data |>
summarise(
x = min(time),
y = max(value) - .05 * (diff(range(value))),
.by = Station
),
by = "Station"
) |>
mutate(
vjust = ifelse(grepl("^Pred1", Source), 0, 1)
)
ggplot(data = filtered_data, aes(x = time, y = value, color = Source)) +
geom_line() +
geom_label(
data = filtered_label,
aes(
label = paste0(
"R²:", round(RSquared, 2), ", NSE:", round(NSE, 2),
", PBIAS:", round(PBIAS, 2)
),
vjust = vjust,
color = Source,
x = x,
y = y
), size = 8 / .pt, hjust = 0, show.legend = FALSE,
label.size = 0,
label.padding = unit(2, "pt")
) +
facet_grid(Station ~ ., scales = "free_y") +
labs(
title = labels$title,
x = "Zeit",
y = labels$y,
color = "Data Source"
) +
scale_color_brewer(palette = "Set1") +
scale_x_datetime(labels = function(x) format(x, "%b %Y"), breaks = "2 month") +
guides(color = guide_legend(title = "")) +
theme_minimal() +
theme(
legend.position = "bottom",
panel.border = element_rect(color = "black", fill = NA, size = 0.4),
panel.grid = element_line(linetype = "dashed")
)
}
final_plots <- lapply(variables, plot_fun)
#> Warning: The `size` argument of `element_rect()` is deprecated as of ggplot2 3.4.0.
#> ℹ Please use the `linewidth` argument instead.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
final_plots
#> [[1]]
#>
#> [[2]]
Upvotes: 1