使用ggplot2与plotly绘制分面柱状图时遭遇字段拆分及分面变量值缺失报错求助
解决ggplot2+plotly绘图的两个错误问题
让我来帮你排查这两个错误的根源并给出可行的解决方案:
错误原因分析
Expected 2 pieces. Missing pieces filled with NA in 1 rows [24216]警告:
这个警告来自separate()函数,说明你的数据集中第24216行的Date.of.Sale格式不符合-分隔的两段结构,导致无法拆分成Sale_year和Sale_month两个字段,函数自动填充了NA。Error: Faceting variables must have at least one value报错:
这是核心问题——你过滤后的数据集是空的!原数据中Date.of.Sale是"YY-Mon"格式(比如"20-Jun"代表2020年6月),但你用separate()提取的Sale_year是两位年份数字,而你过滤的是Sale_year %in% c(16,17)(即2016、2017年),如果你的数据集里没有对应年份的记录,过滤后就没有数据,分面变量Sale_year无值就会触发这个错误。
修正后的完整代码
# Load Libraries library(ggplot2) library(dplyr) options(scipen = 100000) library(scales) library(plotly) library(tidyverse) # Read dataset ura <- read.csv('URAdata_new.csv') # Data cleaning: 修正日期处理逻辑,先过滤格式异常的行 ura_clean <- ura %>% # 只保留符合"两位数字-三位月份缩写"格式的记录 filter(grepl("^\\d{2}-[A-Za-z]{3}$", Date.of.Sale)) %>% # 拆分日期,兼容可能的格式异常 separate(Date.of.Sale, c('Sale_year', 'Sale_month'), sep = '-', extra = "drop", fill = "right") %>% # 转年份为整数,方便后续过滤 mutate(Sale_year = as.integer(Sale_year)) # 提前检查过滤后的数据是否存在 filtered_data <- ura_clean %>% filter(Sale_year %in% c(16, 17) & Postal.District %in% c(2, 5)) # 如果无数据,提前提示 if(nrow(filtered_data) == 0) { stop("No matching records found! Please check if your dataset has data for 2016/2017 and districts 2/5.") } # 绘制ggplot图表 plot_gg <- filtered_data %>% group_by(Sale_year, Postal.District) %>% # 显式指定分组后丢弃分组信息,避免dplyr警告 summarize(avg_price = mean(Price....), .groups = "drop") %>% ggplot(aes(x = as.character(Postal.District), y = avg_price, fill = as.factor(Sale_year))) + # 添加position_dodge让同区域的年份柱子并排显示 geom_col(position = position_dodge(width = 0.8)) + facet_grid(~ as.factor(Sale_year)) + labs(x = 'Postal District', y = 'Average price', title = 'Comparison of unit prices in district 2 and 5 between 2016 and 2017') + scale_fill_discrete(name = "Year of sale", labels = c("2016", "2017")) + theme(plot.title = element_text(colour="red", size=10, face="bold.italic", hjust = 0.5), axis.title.x = element_text(colour="blue", size=14, face="bold"), axis.title.y = element_text(colour="green", size=14, face="bold"), legend.title = element_text(size=8)) + scale_y_continuous(name="Average Price", labels = comma) # 转换为plotly交互图表 Plot2 <- ggplotly(plot_gg) Plot2
关键修正说明
- 日期格式校验:用
grepl()过滤掉格式异常的Date.of.Sale行,同时给separate()添加extra和fill参数,兼容可能的格式问题,避免NA填充警告。 - 空数据提前检查:在绘图前先确认过滤后的数据集是否有记录,提前给出明确提示,避免分面时的无值错误。
- 可视化优化:添加
position_dodge()让同邮区的不同年份柱子并排,提升图表可读性;用.groups = "drop"清理分组残留,避免dplyr的警告信息。
如果运行后仍然提示无数据,需要确认你的数据集里是否真的存在2016/2017年、邮区2/5的记录,可能需要调整过滤条件或检查数据来源。
内容的提问来源于stack exchange,提问作者Chua S Yang
相关产品推荐
相关产品推荐

