R调用ggplotly转换含annotation_raster图表报条件长度大于1错误
问题描述
运行Stack Overflow问题《embed image: ggplot to plotly date issue》中的示例代码时触发运行报错,原代码如下:
library(ggplot2) library(png) library(RCurl) library(plotly) mydf <- data.frame(date = as.Date(c("01/01/1998", "10/01/1998", "15/01/1998", "25/01/1998", "01/02/1998", "12/02/1998", "20/02/1998"), "%d/%m/%Y"), counts = c(12, 10, 2, 24, 15, 1, 14), image = c(NA, "https://www.r-project.org/logo/Rlogo.png", NA, NA, "https://www.r-project.org/logo/Rlogo.png", NA, NA)) mydf # 计算图片显示的宽高 yHeight <- (max(mydf$counts) - min(mydf$counts)) * 0.05 xWidth <- (max(as.numeric(mydf$date)) - min(as.numeric(mydf$date))) * 0.05 # 绘制基础ggplot图 gg2 <- ggplot(mydf, aes(date, counts)) + geom_line() # 遍历数据行添加图片标注 for (x in 1:nrow(mydf)) { row <- mydf[x, ] if(!is.na(row$image)){ # 读取远程图片 img <- readPNG(getURLContent(row$image)) # 通过annotation_raster添加图片图层 gg2 <- gg2 + annotation_raster(img, xmin = as.numeric(row$date) - xWidth/2, xmax = as.numeric(row$date) + xWidth/2, ymin = row$counts - yHeight/2, ymax = row$counts + yHeight/2) } } ggplotly(gg2)
运行后抛出的报错信息为:
Error in if (RasterGeom/length(geoms) > 0.5) "above" else "below" : the condition has length > 1
报错原因
该报错源于ggplotly转换逻辑的兼容缺陷:当ggplot对象通过循环叠加多个annotation_raster栅格图层时,ggplotly内部用于判断栅格显示层级的代码未做输入值收敛,直接将长度大于1的向量传入if条件判断;而R语言中if结构仅接受单逻辑值输入,因此直接触发运行错误。
解决方案
放弃在ggplot层循环叠加annotation_raster再转换为plotly对象的实现路径,直接使用plotly原生的图片标注接口添加嵌入图片,从根源上规避图层转换的兼容问题,修正后的可运行代码如下:
library(ggplot2) library(plotly) mydf <- data.frame(date = as.Date(c("01/01/1998", "10/01/1998", "15/01/1998", "25/01/1998", "01/02/1998", "12/02/1998", "20/02/1998"), "%d/%m/%Y"), counts = c(12, 10, 2, 24, 15, 1, 14), image = c(NA, "https://www.r-project.org/logo/Rlogo.png", NA, NA, "https://www.r-project.org/logo/Rlogo.png", NA, NA)) # 计算图片显示宽高 yHeight <- (max(mydf$counts) - min(mydf$counts)) * 0.05 xWidth <- (max(as.numeric(mydf$date)) - min(as.numeric(mydf$date))) * 0.05 # 生成基础plotly线图 p <- plot_ly(mydf, x = ~date, y = ~counts, type = 'scatter', mode = 'lines') # 构造图片标注配置列表 img_list <- list() valid_img_row <- which(!is.na(mydf$image)) for (i in seq_along(valid_img_row)) { row <- mydf[valid_img_row[i], ] img_list[[i]] <- list( source = row$image, x = as.numeric(row$date), y = row$counts, sizex = xWidth, sizey = yHeight, xref = "x", yref = "y", xanchor = "center", yanchor = "middle" ) } # 批量添加图片并输出图表 p <- p %>% layout(images = img_list) p
运行上述代码即可正常生成带嵌入图片的交互式折线图,不会触发此前的层级判断报错。
内容的提问来源于stack exchange,提问作者Juliette
相关产品推荐
相关产品推荐

