R plotly图中带有悬停信息的线段或矩形

Posted

技术标签:

【中文标题】R plotly图中带有悬停信息的线段或矩形【英文标题】:Line segments or rectangles with hover information in R plotly figure 【发布时间】:2016-12-21 16:30:05 【问题描述】:

我想创建一个线段或矩形的交互式图形,这样当用户将鼠标悬停在其上时,每个线段或矩形都会提供不同的信息。我查看了htmlwidgets showcase,我认为 plotly 看起来很有希望。 (我对其他与 R 相关的方法持开放态度。)

下面是一个简单的例子。我可以创建提供悬停信息的端点(t1 和 t2)的图。但我希望在用户将鼠标悬停在两个端点之间的空间上时出现悬停信息)。

我可以使用add_trace() 添加一条线段,但我无法让悬停工作。如果我添加第二条线段,我会收到一条错误消息:

Error in plot_ly(data = mydat, x = t2, y = y, mode = "markers", hoverinfo = "text",  : 
  requires numeric/complex matrix/vector arguments

我可以使用 layout() 添加矩形,但同样,我无法让悬停工作。

如果有人建议一种方法让悬停参数适用于任何一种方法,我也欢迎有关如何为大量线段/矩形编码的建议(不仅仅是这个简单示例中的 2 个) .

有什么建议吗?

mydat <- data.frame(t1=c(1, 3), t2=c(4, 5), y=c(1, 2), task=c("this", "that"))
library(plotly)

# attempt with one line segment - hover doesn't work
plot_ly(data=mydat, x=t2, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
add_trace(data=mydat, x=t1, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
add_trace(
  x=c(mydat$t1[1], mydat$t2[1]), y=c(mydat$y[1], mydat$y[1]), 
  mode="lines", hoverinfo="text", text=mydat$task[1])

# attempt with both line segments - 
# Error in plot_ly, requires numeric/complex matrix/vector arguments
plot_ly(data=mydat, x=t2, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
add_trace(data=mydat, x=t1, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
add_trace(
  x=c(mydat$t1[1], mydat$t2[1]), y=c(mydat$y[1], mydat$y[1]), 
  mode="lines", hoverinfo="text", text=mydat$task[1]) %*%
add_trace(
  x=c(mydat$t1[2], mydat$t2[2]), y=c(mydat$y[2], mydat$y[2]), 
  mode="lines", hoverinfo="text", text=mydat$task[2])

# attempt with rectangles - hover doesn't work
plot_ly(data=mydat, x=t2, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
add_trace(data=mydat, x=t1, y=y, mode="markers",
  hoverinfo="text", text=task) %>%
layout(shapes=list(
  list(type="rect", x0=mydat$t1[1], x1=mydat$t2[1], xref="x",
    y0=mydat$y[1], y1=mydat$y[1]+0.1, yref="y",
    hoverinfo="text", text=mydat$task[1]),
  list(type="rect", x0=mydat$t1[2], x1=mydat$t2[2], xref="x",
    y0=mydat$y[2], y1=mydat$y[2]+0.1, yref="y",
    hoverinfo="text", text=mydat$task[2])
  ))

【问题讨论】:

【参考方案1】:

您可以通过在线上放置许多点来获取沿线的悬停信息。您无需在这些点上放置标记,因此绘图看起来仍然相同:

NP=100
mydat <- data.frame(t1=seq(1,3,len=NP), t2=seq(4,5,len=NP), y1=rep(1,NP),  y2=rep(2,NP))

plot_ly(data=mydat) %>%
  add_trace(x=t1, y=y1, mode="lines", hoverinfo="text", text="hello") %>%
  add_trace(x=t2, y=y2, mode="lines", hoverinfo="text", text="there") 

将其扩展到矩形,我们可以这样做

plot_ly() %>%
  add_trace(x=c(seq(1,3,len=NP), rep(3,NP), seq(3,1,len=NP), rep(1,NP)),
            y=c(rep(1,NP), seq(1,2,len=NP), rep(2,NP), seq(2,1,len=NP)),
            mode="lines", hoverinfo="text", text="A sublime rectangle") %>%
  layout(hovermode = 'closest')

或者,如果你想分别标记矩形的每一边

plot_ly() %>%
  add_trace(x=c(seq(1,3,len=NP), rep(3,NP), seq(3,1,len=NP), rep(1,NP)),
            y=c(rep(1,NP), seq(1,2,len=NP), rep(2,NP), seq(2,1,len=NP)),
            mode="lines", hoverinfo="text", 
            text=c(rep("bottom",NP),rep("right",NP),rep("top",NP),rep("left",NP))) %>%
  layout(hovermode = 'closest')

对于对角线:

plot_ly() %>%
  add_trace(x=seq(1,3,len=NP), y=seq(1,2,len=NP), mode="lines", hoverinfo="text", text="diagonal") %>%
  layout(hovermode = 'closest')

回答您的额外问题“如何为大量线段/矩形编码”?您没有指定有多少是“大数”。但我能说的是,在 plotly 中添加许多单独的痕迹会使处理速度相当慢。带有大量痕迹的慢得难以忍受。解决此问题的方法是将所有线段添加到单个跟踪中。对于某些效果(例如将颜色与组和图例条目分开控制),可能需要添加分隔段的 NA 值并在add_trace 中使用connectgaps=FALSE 选项(请参阅here 和here),但是对于这个简单的情况,这不是必需的。这是一个最小的例子

line1 <- data.frame(x=seq(3.5,4.5,len=NP), y=rep(2.5,NP), text="hello")
line2 <- data.frame(x=seq(3,3.5,len=NP), y=seq(3,2.5,len=NP), text="mouth")
line3 <- data.frame(x=seq(4.5,5,len=NP), y=seq(2.5,3,len=NP), text="mouth")
line4 <- data.frame(x=rep(4,NP), y=seq(2.75,3.5,len=NP), text="nose")
rect1 <- data.frame(x=c(seq(2,6,len=NP), rep(6,NP), seq(6,2,len=NP), rep(2,NP)),
                    y=c(rep(2,NP), seq(2,4.5,len=NP), rep(4.5,NP), seq(4.5,2,len=NP)),
                    text="head")
rect2 <- data.frame(x=c(seq(2.5,3.5,len=NP), rep(3.5,NP), seq(3.5,2.5,len=NP), rep(2.5,NP)),
                    y=c(rep(3.5,NP), seq(3.5,4,len=NP), rep(4,NP), seq(4,3.5,len=NP)),
                    text="left eye")
rect3 <- data.frame(x=c(seq(4.5,5.5,len=NP), rep(5.5,NP), seq(5.5,4.5,len=NP), rep(4.5,NP)),
                    y=c(rep(3.5,NP), seq(3.5,4,len=NP), rep(4,NP), seq(4,3.5,len=NP)),
                    text="right eye")

trace_dat <- rbind(line1, line2, line3, line4, rect1, rect2, rect3)

plot_ly(data=trace_dat, x=x, y=y, mode="lines", hoverinfo="text", text=text, group = text) %>%
  layout(hovermode = 'closest')

【讨论】:

2020 年,这里有两个问题: 1. 现在使用~ 作为变量。例如。 add_trace(x = ~t1)。第二:这种方法在缩放时会失效。查看演示 here。另请参阅相关的 RStudio 社区帖子here。 谢谢@julianstanley。看看this meta post。如果您有一个适用于较新版本的 plotly 的新答案,请随时在此处将其添加为新答案。如果您正在寻找一个更新的答案并且不知道如何自己解决它,您可以考虑提出一个新问题并参考这个问题以表明它不是重复的。【参考方案2】:

您可以使用 highcharter,它包装了 Highcharts.js 库。

# note i'm renaming y to x, since that's how highcharts will treat this dataset
mydat <- data.frame(t1=c(1, 3), t2=c(4, 5), x=c(1, 2), task=c("this", "that"))

library(highcharter)

highchart(hc_opts = list(
  chart = list(inverted = 'true')
  )) %>% 
  hc_add_series_df(data = mydat, type = 'columnrange',
                   group = task,
                   x = x, low = t1, high = t2)

无需额外代码即可处理大量柱状图,效果很好:

set.seed(123)
n <- 20
largedat <- data.frame(t1 = runif(n, 1, 10), 
                       x = 1:n,
                       task = paste('series', 1:n))
largedat$t2 <- largedat$t1 + runif(n, 2, 5)

highchart(hc_opts = list(
  chart = list(inverted = 'true')
  )) %>% 
  hc_add_series_df(data = largedat, type = 'columnrange',
                   group = task,
                   x = x, low = t1, high = t2) %>%
  hc_legend(enabled = FALSE) # disable legend on this one

【讨论】:

以上是关于R plotly图中带有悬停信息的线段或矩形的主要内容,如果未能解决你的问题,请参考以下文章

如何在 R 树状图中正确着色边缘或绘制矩形?

在R中的多个点之间的图中添加多个线段

将垂直线段添加到动态条形图 ggplot-plotly

R语言可视化散点图(scatter plot)为每一个数据点都绘制指示线段或者都不绘制ggrepel包来帮忙

流程图中的带箭头的线段代表啥?

POJ 1410 判断线段与矩形交点或在矩形内