You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 18:17:05