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

绘制Slope Chart时遇ylim()报错:离散值传入连续刻度

问题:绘制Slope Chart时触发离散值/连续刻度不匹配错误

首次尝试绘制Slope Chart,代码如下:

df1 <- dplyr::data_frame('tests' = c("2023","2024"),
                         'Pre-season Avg.' = c(42.35,51.38),
                         'Post-season Avg.' = c(90.4,86.56))
colnames(df1) <- c("tests", "Pre-season Avg.", "Post-season Avg.")
left_label <- paste(df1$'tests', df1$'Pre-season Avg.')
right_label <- paste(df1$'tests', df1$'Post-season Avg.')
df1$class <- ifelse((df1$'Post-season Avg.' - df1$'Pre-season Avg.') < 0, "red", "dodgerblue")
plot <- ggplot(df1) +
  geom_segment(aes(x=1, xend=2, y="Pre-season Avg.", yend="Post-season Avg.", col=class), size=0.75,
  show.legend=F) +
  geom_vline(xintercept=1, linetype="dashed", size=0.1) +
  geom_vline(xintercept=2, linetype="dashed", size=0.1) +
  scale_color_manual(labels = c("Up","Down"),
                     values=c("red", "dodgerblue")) +
  labs(x="", y="Scores by Average") +
  xlim(0.5,2.5) + ylim(0, (1.1*(max(df1$'Pre-season Avg.', df1$'Post-season Avg.'))))     

plot <- plot + geom_text(label=left_label, y=df1$'Pre-season Avg.', x=rep(1, NROW(
  df1)), hjust=1.1, size=3.5)
plot <- plot + geom_text(label=right_label, y=df1$'Post-season Avg.', x=rep(2, NROW(
  df1)), hjust=-0.1, size=3.5)
plot <- plot + geom_text(label="Pre-season", x=1, y=1.1*(max(df1$'Pre-season Avg.', df1$'Post-season Avg.')),
  hjust=1.2, size=5)
plot <- plot + geom_text(label="Post-season", x=2, y=1.1*(max(df1$'Pre-season Avg.', df1$'Post-season Avg.')),
  hjust=-0.1, size=5)

plot + theme(panel.background = element_blank(), 
          panel.grid = element_blank(),
          axis.ticks = element_blank(),
          axis.text.x = element_blank(),
          panel.border = element_blank(),
          plot.margin = unit(c(1,2,1,2), "cm"))
plot

其中df1$'Pre-season Avg.'和df1$'Post-season Avg.'均为double类型,但运行时触发报错:

Error in `ylim()`:
! Discrete values supplied to continuous scale.
ℹ Example values: "Pre-season Avg." and "Pre-season Avg."
错误原因分析
  • 核心问题出在geom_segment的y和yend参数:你传入的是字符串"Pre-season Avg."和"Post-season Avg.",ggplot2会将这些字符串识别为离散类别,而非对应列中的连续数值,因此和后续设置的连续ylim冲突,触发报错。
  • 你的数据是宽格式(wide format),而ggplot2的设计更适配长格式(tidy format)数据,这也是导致此类错误的常见诱因。
修复方案

方案1:直接修正原代码的参数引用

将geom_segment中带引号的列名字符串替换为实际的列引用(列名含空格时用反引号包裹):

plot <- ggplot(df1) +
  # 关键修改:把y="Pre-season Avg."改成y=`Pre-season Avg.`
  geom_segment(aes(x=1, xend=2, y=`Pre-season Avg.`, yend=`Post-season Avg.`, col=class), size=0.75, show.legend=F) +
  geom_vline(xintercept=1, linetype="dashed", size=0.1) +
  geom_vline(xintercept=2, linetype="dashed", size=0.1) +
  scale_color_manual(labels = c("Up","Down"),
                     values=c("red", "dodgerblue")) +
  labs(x="", y="Scores by Average") +
  xlim(0.5,2.5) + ylim(0, (1.1*(max(df1$'Pre-season Avg.', df1$'Post-season Avg.'))))     

# 后续代码保持不变...

方案2:转成长格式数据(推荐,更符合ggplot2规范)

将宽格式数据转换为长格式,代码会更简洁、易维护:

library(dplyr)
library(tidyr)
library(ggplot2)

# 1. 准备长格式数据
df1 <- tibble(tests = c("2023","2024"),
              `Pre-season Avg.` = c(42.35,51.38),
              `Post-season Avg.` = c(90.4,86.56)) %>%
  # 转长格式:将赛季列合并为一列
  pivot_longer(cols = -tests, names_to = "season", values_to = "avg_score") %>%
  # 给赛季分配x轴位置
  mutate(season_order = ifelse(season == "Pre-season Avg.", 1, 2))

# 2. 计算分数变化方向的颜色
df1 <- df1 %>%
  group_by(tests) %>%
  mutate(class = ifelse(last(avg_score) - first(avg_score) < 0, "red", "dodgerblue")) %>%
  ungroup()

# 3. 绘制Slope Chart
ggplot(df1, aes(x = season_order, y = avg_score, group = tests, color = class)) +
  geom_segment(aes(xend = lead(season_order), yend = lead(avg_score)), size=0.75, show.legend=F) +
  geom_vline(xintercept = 1, linetype="dashed", size=0.1) +
  geom_vline(xintercept = 2, linetype="dashed", size=0.1) +
  # 添加数据标签
  geom_text(aes(label = paste(tests, avg_score)), hjust = ifelse(season_order == 1, 1.1, -0.1), size=3.5) +
  # 添加赛季标题
  geom_text(x=1, y=1.1*max(df1$avg_score), label="Pre-season", hjust=1.2, size=5) +
  geom_text(x=2, y=1.1*max(df1$avg_score), label="Post-season", hjust=-0.1, size=5) +
  scale_color_manual(labels = c("Up","Down"), values=c("red", "dodgerblue")) +
  labs(x="", y="Scores by Average") +
  xlim(0.5,2.5) + 
  ylim(0, 1.1*max(df1$avg_score)) +
  theme(panel.background = element_blank(), 
        panel.grid = element_blank(),
        axis.ticks = element_blank(),
        axis.text.x = element_blank(),
        panel.border = element_blank(),
        plot.margin = unit(c(1,2,1,2), "cm"))

内容的提问来源于stack exchange,提问作者RKeithL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 21:54:56