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

如何修复ggplot绘图时出现的‘Error in strwidth’图例显示错误

嗨,你遇到的问题其实是因为ggplot和base R绘图系统完全不兼容导致的,我来帮你拆解解决:

问题根源

你用ggplot()生成图表后,又调用了base R的legend()函数——这俩属于完全独立的绘图框架:ggplot基于grid系统,而legend()是base R绘图的工具,它需要先触发plot.new()(base的绘图初始化)才能工作,但ggplot根本不会触发这个步骤,所以才会报错plot.new has not been called yet。

解决的核心思路是:用ggplot原生的语法来生成图例,绝对不要混用两个系统的函数。

推荐解决方案:ggplot原生图例生成

你之前的代码里,geom_point(colour = meltdf2$colour)是直接把颜色当成固定值传给点,没有让ggplot把颜色识别为一个需要生成图例的美学映射。我们需要调整成映射模式:

步骤1:(可选但推荐)给颜色对应标签

先给你的colour列匹配对应的等级标签(High/Mid/Low),生成一个因子列来控制图例顺序:

# 用dplyr的case_when更清晰,也可以用ifelse嵌套
library(dplyr)
meltdf2 <- meltdf2 %>%
  mutate(score_level = factor(
    case_when(
      colour == "red2" ~ "High",
      colour == "gold" ~ "Mid",
      colour == "limegreen" ~ "Low"
    ),
    levels = c("High", "Mid", "Low") # 指定图例显示顺序
  ))

步骤2:修改ggplot代码,映射颜色并指定图例

把颜色映射到刚才的score_level列,然后用scale_colour_manual指定对应颜色,ggplot会自动生成图例:

ggplot(data = meltdf2, aes(x = Month, y = variable, group = variable)) +
  geom_line(linetype = "dashed", colour = "grey") +
  geom_point(aes(colour = score_level), size = 3) + # 这里把colour作为美学映射,而非固定值
  scale_x_date(date_breaks = "1 month", date_labels = "%b-%y") +
  scale_colour_manual(
    values = c("High" = "red2", "Mid" = "gold", "Low" = "limegreen"), # 匹配颜色和标签
    name = "Score Level" # 可以自定义图例标题,不需要就设为NULL
  ) +
  theme(
    axis.title.y = element_blank(),
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.line.x = element_line(colour = "darkgrey"),
    panel.background = element_rect(fill = "white"),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.position = "topleft" # 指定图例位置,和你原来的需求一致
  )

简化方案:无需新建列

如果不想额外生成score_level列,可以直接用scale_colour_identity把颜色值本身映射成图例,同时指定标签:

ggplot(data = meltdf2, aes(x = Month, y = variable, group = variable)) +
  geom_line(linetype = "dashed", colour = "grey") +
  geom_point(aes(colour = colour), size = 3) +
  scale_x_date(date_breaks = "1 month", date_labels = "%b-%y") +
  scale_colour_identity(
    guide = "legend", # 强制生成图例(默认identity scale不生成图例)
    labels = c("red2" = "High", "gold" = "Mid", "limegreen" = "Low"),
    breaks = c("red2", "gold", "limegreen"), # 控制图例顺序
    name = "Score Level"
  ) +
  theme(
    # 保留你原来的theme设置
    axis.title.y = element_blank(),
    axis.text.y = element_blank(),
    axis.ticks.y = element_blank(),
    axis.line.x = element_line(colour = "darkgrey"),
    panel.background = element_rect(fill = "white"),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    legend.position = "topleft"
  )

关键提醒

永远不要把ggplot和base R的绘图函数(比如legend()、title()、axis()等)混用,它们的底层逻辑完全不同,必然会导致冲突。所有图表元素都应该用ggplot的语法来调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:53:20