ggplot正态分布图修改需求:图例与X轴优化调整
解决方案
修改内容说明
- 图例优化:将相同颜色的标准差区间合并为单个图例项,按绿色(68.26%)、蓝色(27.2%)、橙色(4.26%)、红色(0.28%)的顺序排列
- X轴分界值设置:直接使用均值与标准差计算得到的区间分界点作为X轴刻度,清晰显示颜色变化的边界
- 保留侧边百分比位置:维持原有的均值和标准差注释文本位置不变
修改后的完整R代码
# 安装并加载所需包 install.packages("tidyquant") install.packages("GauPro") install.packages("kernlab") library(tidyquant) library(GauPro) library(kernlab) library(tidyverse) library(dplyr) library(ggplot2) Sys.setlocale(category = "LC_ALL", locale = "Norwegian_Norway.1252") # 获取Equinor历史股价数据,计算股价突破50SMA后1个月和3个月的收益率 eqnr <- tq_get("EQNR.OL", from = "2018-01-01", to = "2022-01-01") %>% tq_mutate(select = close, mutate_fun = SMA, n = 50, col_rename = "sma") %>% mutate(cross = if_else(close > sma, 1, 0), first_cross = cross - lag(cross), price_1m = lead(close, 20), price_3m = lead(close, 60)) %>% filter(first_cross == 1) %>% mutate(across(contains("price"), ~ round((.x / close - 1) *100, 2), .names = "{.col}_change")) # 获取Aker BP历史股价数据,计算股价突破50SMA后1个月和3个月的收益率 akrbp <- tq_get("AKRBP.OL", from = "2018-01-01", to = "2022-01-01") %>% tq_mutate(select = close, mutate_fun = SMA, n = 50, col_rename = "sma") %>% mutate(cross = if_else(close > sma, 1, 0), first_cross = cross - lag(cross), price_1m = lead(close, 20), price_3m = lead(close, 60)) %>% filter(first_cross == 1) %>% mutate(across(contains("price"), ~ round((.x / close - 1) *100, 2), .names = "{.col}_change")) # 将所有石油和能源股数据合并为一个数据框 Olje_Energi <- bind_rows(eqnr, akrbp) # 根据均值和标准差定义X轴范围 GJ_snitt <- mean(Olje_Energi$price_1m_change, na.rm = TRUE) Standardavvik <- sd(Olje_Energi$price_1m_change, na.rm = TRUE) x_verdier <- seq(-3*Standardavvik + GJ_snitt, 3*Standardavvik + GJ_snitt, length.out = 50) # 计算这些收益率的概率密度 normalfordeling <- dnorm(x_verdier, mean = GJ_snitt, sd = Standardavvik) # 将数值四舍五入到两位小数 x_verdier_avrundet <- round(x_verdier, 2) df <- data.frame(x_verdier_avrundet, normalfordeling) # 在数据框中添加新列,标记每个四舍五入后的X值所属的标准差区间 df$Sigma <- cut(df$x_verdier_avrundet, breaks = seq(-3 * Standardavvik + GJ_snitt, 3 * Standardavvik + GJ_snitt, by = Standardavvik), labels = c("-3σ", "-2σ", "-σ", "σ", "2σ", "3σ")) # 新增颜色分组列,合并相同颜色的区间,用于图例显示 df$color_group <- case_when( df$Sigma %in% c("-σ", "σ") ~ "68.26%", df$Sigma %in% c("-2σ", "2σ") ~ "27.2%", df$Sigma %in% c("-3σ", "3σ") ~ "4.26%", is.na(df$Sigma) ~ "0.28%" ) # 设置分组顺序,对应图例从上到下的颜色顺序:绿色、蓝色、橙色、红色 df$color_group <- factor(df$color_group, levels = c("68.26%", "27.2%", "4.26%", "0.28%")) # 创建柱状图,为每个标准差区间设置不同颜色 ggplot(df, aes(x = x_verdier_avrundet, y = normalfordeling, fill = color_group)) + geom_bar(stat = "identity", col = "black") + labs(title = "Fordeling av avkastning basert på standardavvik", x = "Avkastning", y = "Sannsynlighetstetthet") + scale_fill_manual(name = "Sannsynlighet", values = c("68.26%" = "green", "27.2%" = "blue", "4.26%" = "orange", "0.28%" = "red")) + # 设置X轴刻度为颜色变化的分界值 scale_x_continuous(breaks = seq(-3 * Standardavvik + GJ_snitt, 3 * Standardavvik + GJ_snitt, by = Standardavvik), labels = function(x) round(x, 2)) + theme_minimal() + theme(legend.position = "right", plot.background = element_rect(size = 3, color = "black", fill = "white")) + # 保留原有的均值和标准差注释位置 annotate("text", x = GJ_snitt, y = max(df$normalfordeling), label = paste("Gjennomsnitt:", round(GJ_snitt, 2), "%"), vjust = 0.5, hjust = -.3) + annotate("text", x = GJ_snitt, y = max(df$normalfordeling), label = paste("Standardavvik:", round(Standardavvik, 2), "%"), vjust = 2, hjust = -.3)
内容的提问来源于stack exchange,提问作者Erlend
相关产品推荐
相关产品推荐

