R使用plotly绘图报plot.new has not been called yet错误如何解决
报错核心原因
你遇到这个报错的本质是混用了两套完全独立的R绘图体系的语法:
axis()、abline()、mtext()、pch、cex、ylim、axes这些函数和参数,全部属于R内置的base基础绘图系统,只能在R本地的栅格绘图设备中运行,调用时要求已经通过plot()等base绘图命令启动了绘图窗口。plot_ly()生成的是plotly的交互式Web绘图对象,和base绘图系统完全不互通,你在layout()里直接传入axis()这类base函数调用时,R会尝试寻找base系统的活跃绘图设备,找不到就直接抛出plot.new has not been called yet错误。
你的代码里还存在几个会导致后续运行失败的问题:
plot_ly中映射的y = ~res列在你提供的示例数据中不存在,示例数据只有Age和Pertubation两列- 保存环节错误地将原生plotly对象传入了
ggplotly(),这个函数仅用于转换ggplot2生成的绘图对象,直接传入plotly对象会触发类型错误 - plotly的
layout()函数仅接受自身约定的配置参数,不支持直接传入base绘图的函数调用
修复方案
- 全部替换base绘图逻辑为plotly原生语法:
- 坐标轴刻度、字号配置:写入
layout()对应的xaxis/yaxis/yaxis2(右侧副轴)参数中,不再使用axis() - 参考线:通过
layout()的shapes参数配置,不再使用abline() - 边距/轴标题:通过轴配置的
title参数设置,不再使用mtext() - 点样式、轴范围、字号:分别写入
marker、轴的range、font相关参数,不再使用base绘图的pch/cex/ylim参数
- 坐标轴刻度、字号配置:写入
- 修正对象调用逻辑:
- 将y轴映射替换为你实际需要绘制的列(示例数据中为
Pertubation) - 保存时直接将plotly对象传入
saveWidget(),不再嵌套ggplotly()
- 将y轴映射替换为你实际需要绘制的列(示例数据中为
修复后的可运行参考代码:
# 加载依赖 library(plotly) library(htmlwidgets) # 示例数据 Age <-c(69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183) Pertubation <- c(0.002967936,-0.794788368,-1.561544673,-2.938300977,-2.956057282,-3.724813586,-3.84656989,-4.000326195,-3.491082499,-3.705838803,-3.008595108,-3.439351412,-2.518107716,-2.108864021,-1.892620325,-2.175376629,-2.547132934,-2.694889238,-3.985645543,-2.702401847,-3.203158151,-3.238914456,-2.60867076,-2.564427064,-3.254183369,-1.973939673,-0.731695977,-0.625452282,-0.966208586,-0.811964891,-0.018721195,0.320522501,-0.227233804,-0.046990108,-0.820746412,-0.846502717,1.067740979,1.470984675,1.00222837,0.448472066,1.139715762,1.275959457,0.989203153,0.904446848,0.607690544,0.20693424,1.084177935,1.114421631,0.625665327,0.292909022,-0.833847282,-2.208603586,-3.397359891,-4.339116195,-4.950872499,-5.518628804,-6.992385108,-7.023141413,-8.193897717,-8.580654021,-9.428410326,-10.92316663,-11.37392293,-12.21167924,-12.77643554,-13.14219185,-13.67394815,-14.19370446,-14.16046076,-15.29121706,-16.06197337,-16.11472967,-16.29348598,-17.62424228,-17.79699859,-19.42675489,-19.6625112,-20.3642675,-21.4460238,-22.05378011,-23.87553641,-24.06129272,-25.00604902,-25.80180533,-26.77656163,-27.40431793,-28.86407424,-29.45483054,-29.37758685,-30.48534315,-30.07209946,-29.86985576,-29.82561207,-30.46936837,-30.56412467,-30.24788098,-29.40463728,-29.76939359,-29.11314989,-29.0989062,-29.2466625,-29.1654188,-29.28217511,-29.11493141,-28.44568772,-28.65344402,-28.43520033,-28.71795663,-29.06871293,-29.66546924,-28.39422554,-29.68398185,-29.73973815,-29.34349446,-29.45325076) plot_df <- data.frame(Age, Pertubation) # 按需替换为你代码中的实际变量值 i <- 1 lambda <- 0.5 crit1 <- -5 # 替换为原代码中dif$eval_day生成的刻度序列 x_ticks <- seq(min(plot_df$Age), max(plot_df$Age), by = 5) # 生成绘图对象 Pertubation_graph <- plot_ly(plot_df, x = ~Age, y = ~Pertubation, type = "scatter", mode = "markers", # 对应原代码pch=10、cex=0.5的点样式 marker = list(symbol = 10, size = 5) ) %>% layout( title = paste0("Pig ID:", i, ", Lambda =", lambda, "<br>Difference between CFI and TTC"), plot_bgcolor = "#ffffff", # 底部X轴配置,对应原axis(1)设置 xaxis = list( title = "Age (d)", tickmode = "array", tickvals = x_ticks, tickfont = list(size = 13.2), # 对应cex.axis=1.1 titlefont = list(size = 14.4) # 对应cex.lab=1.2 ), # 左侧Y轴配置,对应原axis(2)设置 yaxis = list( title = "Amount of difference: CFI - TTC (kg)", range = c(min(plot_df$Pertubation) - 1, max(plot_df$Pertubation) + 1), # 替换为原代码的ylim范围 tickfont = list(size = 13.2), titlefont = list(size = 14.4) ), # 右侧Y轴配置,对应原axis(4)设置 yaxis2 = list( title = "Percentage of difference: CFI - TTC (%)", overlaying = "y", side = "right", tickfont = list(size = 13.2, color = "blue"), titlefont = list(size = 14.4, color = "blue"), color = "blue" ), titlefont = list(size = 18), # 对应cex.main=1.5 # 参考线配置,对应原abline设置 shapes = list( list(type = "line", x0 = min(plot_df$Age), x1 = max(plot_df$Age), y0 = crit1, y1 = crit1, line = list(color = "red", dash = "dash")), list(type = "line", x0 = min(plot_df$Age), x1 = max(plot_df$Age), y0 = 0, y1 = 0, line = list(color = "red")) ) ) # 保存为HTML文件,替换为你实际的存储路径 saveWidget(Pertubation_graph, file = "pertubation_plot.html")
额外说明
- base绘图的
cex是相对默认字号(12px)的缩放倍数,直接用12乘以对应cex值就能得到plotly中匹配的字号 - 如果需要给右侧Y轴绑定对应的数据,只需要新增一个标记为
yaxis = "y2"的绘图trace即可 - 后续使用plotly绘图时不要插入任何base绘图函数,两类绘图系统的设备完全独立,无法互相操作
内容的提问来源于stack exchange,提问作者Lam Tùng
相关产品推荐
相关产品推荐

