ggplot绘制带密度曲线的直方图报错:Mapping需用aes()/aes_()
解决带有密度曲线的直方图拟合错误
咱们先拆解一下你遇到的问题:Error: Mapping should be created with aes() or aes_()主要是因为geom_line里的映射没有明确指定x、y参数,另外代码里还有几处数据整理的小问题,咱们一步步来修正:
第一步:修正数据整理的错误
你的代码里有两处关键的数据处理问题:
- 合并actual数据时,away组错误复用了home的进球数据,应该替换成
actual$goals_team_away - poisson数据集是宽格式(home/away各一列),需要先转成长格式才能按type分组计算均值
第二步:修正ggplot的映射错误
geom_line必须明确指定x和y的映射关系,而且要确保密度曲线的y轴尺度和直方图的比例匹配(直方图用的是比例prop,密度曲线也要对应调整)
修正后的完整代码
simyears = 1819 actual <- read_rds(here::here(paste0("/data/database_match_results_", simyears, ".rds"))) %>% filter(between(matchday, 21, max(matchday))) # 改用actual自身的matchday范围更稳妥 # 正确整理actual数据集的home/away进球数据 data <- bind_rows( data.frame(type = "home", value = actual$goals_team_home, stringsAsFactors = FALSE), data.frame(type = "away", value = actual$goals_team_away, stringsAsFactors = FALSE) ) # 将poisson数据集转成长格式,计算每组的均值mu poisson_long <- poisson %>% pivot_longer(cols = c(Goals_team_home, Goals_team_away), names_to = "type", values_to = "value") %>% mutate(type = ifelse(type == "Goals_team_home", "home", "away")) estimate <- poisson_long %>% group_by(type) %>% summarize(mu = mean(value)) # 生成密度曲线数据集,并和实际数据的比例合并 dens <- expand.grid(value = 0:max(data$value), type = c("away", "home"), stringsAsFactors = FALSE) %>% inner_join(estimate) %>% mutate(density = dpois(value, mu)) prop <- data %>% group_by(type, value) %>% summarize(count = n()) %>% group_by(type) %>% mutate(prop = count / sum(count)) tmp_actual <- left_join(dens, prop) %>% replace_na(list(prop = 0, count = 0)) # 修正ggplot的映射,明确x/y参数并对齐分组 ggplot(tmp_actual, aes(x = value, fill = type)) + geom_col(aes(weight = prop), position = "dodge") + # 用geom_col适配预计算的比例 geom_line(aes(x = value, y = density, color = type), position = position_dodge(width = 0.9)) # 让曲线和直方图分组对齐
关键修正点说明
- 把
geom_histogram换成geom_col,因为我们已经提前计算了比例,用weight=prop绘制比例直方图更直观 geom_line里明确指定x=value, y=density,添加position_dodge(width=0.9)让曲线和分组直方图对齐,避免重叠- 修正了poisson数据集的格式转换,确保能正确按home/away分组计算均值
内容的提问来源于stack exchange,提问作者mugdi
相关产品推荐
相关产品推荐

