ggplot绘制两数据框图形时如何保持相同类别配色一致
配色不一致的核心原因
你的代码存在3个直接导致配色错位的问题:
- 折线图将
Topic映射到了color(线条颜色)美学,但你仅配置了scale_fill_manual(填充色标度)的配色,没有给线条颜色指定色板,折线默认调用ggplot自带配色,完全没用到你提前定义的my_cols_one。 - 每个子图设置标度
limits时,使用的是当年数据子集的unique(.x$Topic),不同年份子集的Topic出现顺序不固定,会直接导致颜色和Topic的映射关系错位。 - 代码存在多处笔误:排序df_two时错误引用了df_one的时间列、df_two聚合前未生成
created_at字段、折线图y轴映射了不存在的avg_sentiment列、日期转换未指定匹配的格式(你的日期是日/月/年格式,默认转换会解析错误),这些问题也会间接导致绘图异常。
修正步骤
1. 固定全局Topic-颜色映射
不要使用子集的Topic列表做映射,提前固定全量Topic的顺序,保证所有图的颜色匹配规则完全统一:
library(randomcoloR) library(tidyverse) library(lubridate) library(gridExtra) # 取两个数据框的所有Topic值,固定顺序 all_topics <- unique(c(df_one$Topic, df_two$Topic)) # 生成对应数量的配色,按固定Topic顺序命名 my_cols <- distinctColorPalette(length(all_topics)) names(my_cols) <- all_topics
2. 修正df_one的预处理和面积图绘制代码
补全笔误,固定fill标度的limits为全量Topic列表:
# df_one预处理:指定日期格式,避免解析错误 df_one$Timestamp <- as.Date(df_one$Timestamp, format = "%d/%m/%Y") df_one <- df_one[order(df_one$Timestamp),] list_one <- df_one %>% mutate(year = year(Timestamp)) %>% split(.$year) %>% map(~ggplot(.x, aes(x=Timestamp, y=Value_A, fill=Topic)) + scale_x_date(date_breaks = '1 month', date_labels = "%b-%y")+ geom_area(alpha=0.6 , linewidth=1, colour="black", position = position_fill())+ theme(legend.position="bottom", legend.box = "horizontal")+ ggtitle("Reliable")+ guides(fill = guide_legend(nrow = 2, label.position = "bottom")) + # 固定limits为全量Topic,保证映射一致 scale_fill_manual(NULL, values = my_cols, limits = all_topics) )
3. 修正df_two的预处理和折线图绘制代码
补上scale_color_manual调用同一套色板,修正所有笔误,固定color标度的limits:
# df_two预处理:修正日期解析、排序、聚合逻辑的笔误 df_two$Timestamp <- as.Date(df_two$Timestamp, format = "%d/%m/%Y") df_two <- df_two[order(df_two$Timestamp),] df_two <- df_two %>% mutate(created_at = floor_date(Timestamp, "15 days")) %>% group_by(created_at, Topic) %>% summarise(Average_Value = mean(Value_B), .groups = "drop") list_two <- df_two %>% mutate(year = year(created_at)) %>% split(.$year) %>% map(~ggplot(.x, aes(x=created_at, y=Average_Value, color=Topic)) + scale_x_date(date_breaks = '1 month', date_labels = "%b-%y")+ geom_line(linewidth=1)+ theme(legend.position="bottom", legend.box = "horizontal", plot.background = element_blank())+ # 对应color美学修改向导 guides(color = guide_legend(nrow = 2, label.position = "bottom")) + # 给线条颜色指定同一套色板,固定limits为全量Topic scale_color_manual(NULL, values = my_cols, limits = all_topics)+ labs(x = 'Date', y = 'Average Value', color="") )
4. 按年度配对拼接图形
直接拼接两个列表会出现3张面积图全部排完再排3张折线图的问题,需要按年交叉排列,实现同一年的面积图、折线图上下配对:
# 按年份交叉组合图形 year_list <- sort(intersect(names(list_one), names(list_two))) plot_order <- unlist(lapply(year_list, function(y) c(list_one[[y]], list_two[[y]])), recursive = F) do.call("grid.arrange", c(plot_order, ncol=2))
修正后所有图中相同Topic的颜色会完全统一,图形排布也符合分年度上下对照的需求。
内容的提问来源于stack exchange,提问作者AneesBaqir
相关产品推荐
相关产品推荐

