如何自定义两个变量的图例?

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

如何为作物类型和氮处理制作一个图例,如此处所示 [![在此处输入图像描述][1]][1]?我想用

geom_point
制作实线表示高氮,用
geom_point
制作虚线表示低氮。 这是数据

library(dplyr)
library(ggplot2)

# Create a dummy dataset
set.seed(123)
dummy_data <- data.frame(
  Rotation_Group = rep("Dummy Rotation Group", 32),
  Sp = rep(c("B/B", "B/Bd", "C/B", "P/B"), each = 8),  # Crop types
  Nitrogen = rep(c("High N", "Low N"), times = 16),    # Nitrogen treatment
  Date = rep(seq(as.Date("2024-03-12"), by = "months", length.out = 4), each = 2, times = 4),  # Sampling dates
  min_n_kgha = c(
    # Mineral N data (random numbers for the example)
    sample(50:120, 8), sample(30:80, 8),
    sample(50:100, 8), sample(30:70, 8)
  )
)

plot_rotation_group <- function(rotation_group_label) {
  # Filter data for the specific rotation group
  mn_aggregated <- dummy_data %>%
    filter(Rotation_Group == rotation_group_label) %>%
    group_by(Sp, Nitrogen, Date) %>%
    summarise(mean_min_n_kgha = mean(min_n_kgha, na.rm = TRUE), .groups = "drop")
  
  # Convert the Date to a factor for equally spaced categorical labels
  mn_aggregated$Date_Factor <- factor(mn_aggregated$Date, levels = unique(mn_aggregated$Date))
  
  # Generate the plot for this specific group
  ggplot(mn_aggregated, aes(x = Date_Factor, y = mean_min_n_kgha, colour = Sp, group = interaction(Sp, Nitrogen))) +
    geom_point(size = 4) +  # Add points for each data observation
    geom_smooth(aes(linetype = Nitrogen), linewidth = 1.5, method = 'loess', formula = 'y ~ x', se = FALSE) +  # Add smooth trend lines without confidence intervals
    
    # Line type: solid for High N, dashed for Low N
    scale_linetype_manual(values = c("High N" = "solid", "Low N" = "dashed")) +
    
    # Use scale_x_discrete to space the dates equally and add some padding on either side
    scale_x_discrete(labels = format(unique(mn_aggregated$Date), "%b %d"),
                     expand = expansion(mult = c(0.1, 0.1))) +  # Add padding to the x-axis
    
    # Ensure y-axis starts at 0
    scale_y_continuous(limits = c(0, NA), breaks = seq(0, 500, 20)) +  # Force the y-axis to start at 0, let max scale automatically
    
    labs(x = "Date of sampling", y = "Mineral N (kg/ha)", title = rotation_group_label) +  # Custom title for the plot
    
    # Adjust theme for more space and better readability
    theme_minimal() +  
    theme(plot.margin = unit(c(1, 1, 1, 1), "cm")) +  # Adjust margins around the plot
    
    # Separate color and linetype legends with extended line length for linetype
    guides(
      colour = guide_legend(
        title = "Crop Type",  # Legend for different species/crops
        override.aes = list(size = 4)
      ),
      linetype = guide_legend(
        title = "Nitrogen Treatment",  # Separate legend for High N and Low N linetype
        override.aes = list(size = 1.5, keywidth = 2)  # Extend the line in the linetype legend
      )
    )
}

# Test the plot with the dummy data
plot_rotation_group("Dummy Rotation Group")``` 

[![enter image description here][2]][2]


  [1]: https://i.sstatic.net/2C3syBM6.png
  [2]: https://i.sstatic.net/Z4KdEuHm.png
r ggplot2
1个回答
0
投票

一种选择是将两个变量的“交互”映射到

color
linetype
上,然后使用相应的颜色和线型调色板:

library(tidyverse)

plot_rotation_group <- function(rotation_group_label) {
  # Filter data for the specific rotation group
  mn_aggregated <- dummy_data %>%
    filter(Rotation_Group == rotation_group_label) %>%
    group_by(Sp, Nitrogen, Date) %>%
    summarise(mean_min_n_kgha = mean(min_n_kgha, na.rm = TRUE), .groups = "drop")

  # Convert the Date to a factor for equally spaced categorical labels
  mn_aggregated$Date_Factor <- factor(mn_aggregated$Date, levels = unique(mn_aggregated$Date))

  pal_color <- mn_aggregated |>
    distinct(Sp) |>
    mutate(color = scales::hue_pal()(n()))

  pal_lty <- c("High N" = "solid", "Low N" = "dashed") |>
    tibble::enframe("Nitrogen", "linetype")

  pals <- mn_aggregated |>
    distinct(Sp, Nitrogen) |>
    left_join(pal_color) |>
    left_join(pal_lty) |>
    unite(category, Sp, Nitrogen, sep = " ")

  pal_color <- pals |>
    select(category, color) |>
    tibble::deframe()
  pal_lty <- pals |>
    select(category, linetype) |>
    tibble::deframe()

  # Generate the plot for this specific group
  ggplot(mn_aggregated, aes(
    x = Date_Factor, y = mean_min_n_kgha,
    colour = paste(Sp, Nitrogen),
    linetype = paste(Sp, Nitrogen)
  )) +
    geom_point(size = 4) + # Add points for each data observation
    geom_smooth(
      aes(group = interaction(Sp, Nitrogen)),
      linewidth = 1.5,
      method = "loess", formula = "y ~ x", se = FALSE
    ) + # Add smooth trend lines without confidence intervals
    scale_linetype_manual(
      values = pal_lty
    ) +
    scale_color_manual(
      values = pal_color
    ) +
    # Use scale_x_discrete to space the dates equally and add some padding on either side
    scale_x_discrete(
      labels = format(unique(mn_aggregated$Date), "%b %d"),
      expand = expansion(mult = c(0.1, 0.1))
    ) + # Add padding to the x-axis
    # Ensure y-axis starts at 0
    scale_y_continuous(limits = c(0, NA), breaks = seq(0, 500, 20)) + # Force the y-axis to start at 0, let max scale automatically
    labs(x = "Date of sampling", y = "Mineral N (kg/ha)", title = rotation_group_label) + # Custom title for the plot
    # Adjust theme for more space and better readability
    theme_minimal() +
    theme(
      plot.margin = unit(c(1, 1, 1, 1), "cm"),
      legend.key.width = unit(2, "cm")
    ) + # Adjust margins around the plot

    # Separate color and linetype legends with extended line length for linetype
    guides(
      colour = guide_legend(
        title = "Crop Type and Nitrogen Treatment",
        override.aes = list(size = 4, linewidth = 1.5, keywidth = 2)
      ),
      linetype = guide_legend(
        title = "Crop Type and Nitrogen Treatment"
        #override.aes = list(size = 4, linewidth = 1.5, keywidth = 2)
      )
    )
}

# Test the plot with the dummy data
plot_rotation_group("Dummy Rotation Group")

enter image description here

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