如何在ggplot2的facet_grid中移除指定列并优化空白区域?
问题描述
我有以下R代码生成热力图:
tmp <- data.frame( "channel_topic" = rep(LETTERS[seq(1:16)],9), "p1_age_cat_complete" = rep(1:9, each = 16), "n" = sample(100, size = 144, replace = TRUE)) |> group_by(channel_topic) |> mutate(n_group = sum(n))|> group_by(n_group) |> mutate(group_id = abs(cur_group_id()-17)) |> ungroup() |> mutate(group_id = ifelse(str_detect(channel_topic, "N"), 99, ifelse(str_detect(channel_topic, "O"), 100, ifelse(str_detect(channel_topic, "P"), 101, group_id)))) |> mutate(facets = ifelse(group_id < 99,"1","2"), facets_2 = ifelse(p1_age_cat_complete == "9", "2","1")) ggplot(tmp) + facet_grid( cols = vars(facets_2), rows = vars(facets), scales = "free_y", space = "free_y", ) + geom_tile( aes( x = p1_age_cat_complete, y = reorder(channel_topic, -group_id), fill = n ) ) + theme( axis.text.x = element_text(angle = 90) ) + labs( x = "Alter", y = "Channel Topic", fill = "Anzahl", subtitle = paste("N = ", sum(tmp$n), sep = "") ) + theme( panel.background = element_rect(fill = "white", colour = "white"), panel.grid.major = element_line(colour = "gray90"), panel.grid.minor = element_line(colour = "grey95"), plot.subtitle = element_text(hjust = 1), axis.text.x = element_text(angle = 90), strip.background = element_blank(), strip.text = element_blank() ) + scale_x_discrete(limits = 1:9)
当前图表存在空列区域,我需要实现:
- 左侧面板移除“9”列
- 右侧面板仅保留“9”列
- 消除空列区域,只保留类似y轴的少量间隔
解决方案
核心思路是针对不同面板精准筛选对应数据,同时调整分面与坐标轴设置,具体修改如下:
1. 数据筛选处理
给数据集新增标记列,过滤掉各面板不需要的行:
tmp <- tmp |> mutate(keep = case_when( facets_2 == "1" & p1_age_cat_complete != "9" ~ TRUE, # 左侧面板保留非9的列 facets_2 == "2" & p1_age_cat_complete == "9" ~ TRUE, # 右侧面板只保留9列 TRUE ~ FALSE )) |> filter(keep) # 移除不需要的行
2. 调整ggplot设置
- 移除强制x轴显示1-9的
scale_x_discrete(limits = 1:9),让坐标轴自适应现有数据 - 将
facet_grid的scales改为"free",让x轴根据面板实际数据自由缩放,避免空列占位
修改后的完整代码
library(tidyverse) tmp <- data.frame( "channel_topic" = rep(LETTERS[seq(1:16)],9), "p1_age_cat_complete" = rep(1:9, each = 16), "n" = sample(100, size = 144, replace = TRUE)) |> group_by(channel_topic) |> mutate(n_group = sum(n))|> group_by(n_group) |> mutate(group_id = abs(cur_group_id()-17)) |> ungroup() |> mutate(group_id = ifelse(str_detect(channel_topic, "N"), 99, ifelse(str_detect(channel_topic, "O"), 100, ifelse(str_detect(channel_topic, "P"), 101, group_id)))) |> mutate(facets = ifelse(group_id < 99,"1","2"), facets_2 = ifelse(p1_age_cat_complete == "9", "2","1")) |> # 新增筛选逻辑 mutate(keep = case_when( facets_2 == "1" & p1_age_cat_complete != "9" ~ TRUE, facets_2 == "2" & p1_age_cat_complete == "9" ~ TRUE, TRUE ~ FALSE )) |> filter(keep) ggplot(tmp) + facet_grid( cols = vars(facets_2), rows = vars(facets), scales = "free", # 让x/y轴自由适配面板数据 space = "free_y", ) + geom_tile( aes( x = p1_age_cat_complete, y = reorder(channel_topic, -group_id), fill = n ) ) + labs( x = "Alter", y = "Channel Topic", fill = "Anzahl", subtitle = paste("N = ", sum(tmp$n), sep = "") ) + theme( panel.background = element_rect(fill = "white", colour = "white"), panel.grid.major = element_line(colour = "gray90"), panel.grid.minor = element_line(colour = "grey95"), plot.subtitle = element_text(hjust = 1), axis.text.x = element_text(angle = 90), strip.background = element_blank(), strip.text = element_blank() )
关键改动说明
- 从数据层面直接移除不需要的行,彻底消除空列占位的根源
- 调整分面缩放规则,让坐标轴仅显示面板内存在的类别
- 去掉强制的x轴范围限制,实现面板间的自适应布局
内容的提问来源于Stack Exchange,提问作者Aaron Philipp
相关产品推荐
相关产品推荐

