为堆叠条形图的每个分栏设置专属父色及内部渐变色
Got it, let's break this down so you can get exactly the chart you want. You have 18 main categories (each bar on the x-axis), each stacked with 39 sub-levels, and you want every main bar to have its own unique parent color—with the sub-levels inside each bar fading from that parent color (light to dark, or reverse). Here's how to pull this off:
Step 1: Set Up Your Data (or Simulate It)
First, let's assume your data looks like this (replace this with your actual dataset):
library(ggplot2) library(scales) library(dplyr) # Simulate a dataset matching your structure: 18 main cats, 39 sub cats each set.seed(123) df <- expand.grid( main_category = paste0("Group_", 1:18), sub_level = paste0("Level_", 1:39) ) %>% mutate(value = sample(1:100, n(), replace = TRUE)) # Replace with your actual values
Step 2: Assign Parent Colors to Each Main Category
We'll first pick 18 distinct parent colors (you can customize these to fit your brand or preferences):
# Generate 18 distinct parent colors using the hue palette (adjustable!) parent_colors <- hue_pal(h = c(0, 360), c = 80, l = 60)(18) names(parent_colors) <- unique(df$main_category)
Tweak the h, c, and l arguments in hue_pal() to adjust the hue range, saturation, and lightness of your parent colors if you want more contrast.
Step 3: Generate Gradient Colors for Each Sub-Level
Next, we'll create a gradient of 39 colors for each main category, based on its parent color. We'll use colorRampPalette to fade from a lighter version of the parent color to the parent itself (reverse the order if you want dark-to-light):
# Create a list of gradient color sets (one per main category) gradient_sets <- lapply(parent_colors, function(base_color) { # Fade from a lighter shade of the parent color to the parent color colorRampPalette(c(lighten(base_color, 0.5), base_color))(39) }) # Map each sub-level in its main category to the correct gradient color df <- df %>% group_by(main_category) %>% mutate( # Ensure sub-levels are ordered correctly (adjust if your sub_level has a natural order) sub_order = as.integer(factor(sub_level)), fill_color = gradient_sets[[unique(main_category)]][sub_order] ) %>% ungroup()
If your sub_level variable has a specific order (like numeric levels), use that instead of factor(sub_level) to make sure the gradient aligns with your hierarchy.
Step 4: Build the Plot
Now we'll plot using the custom colors we generated. We use scale_fill_identity because we're mapping pre-defined colors directly:
ggplot(df, aes(x = main_category, y = value, fill = fill_color)) + geom_bar(stat = "identity", color = "grey", size = 0.2) + # Add grey borders for clarity # Use our custom colors and add a legend for sub-levels scale_fill_identity( guide = "legend", labels = unique(df$sub_level), name = "Sub Levels" ) + labs(x = "Main Categories", y = "Value") + # Rotate x-axis labels so they're readable theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))
Quick Adjustments You Might Want
- Reverse the gradient: Swap the order inside
colorRampPalettetoc(base_color, lighten(base_color, 0.5))for dark-to-light fading. - More distinct parent colors: Try using
viridis_pal()(18)instead ofhue_pal()for colorblind-friendly parent colors. - Smoother gradients: If 39 steps feel abrupt, adjust the lightness value (e.g.,
lighten(base_color, 0.3)for a smaller range between light and dark).
内容的提问来源于stack exchange,提问作者nicole

