在交互式绘图中提取鼠标点击的精确坐标

Posted

技术标签:

【中文标题】在交互式绘图中提取鼠标点击的精确坐标【英文标题】:Extracting the exact coordinates of a mouse click in an interactive plot 【发布时间】:2018-07-09 15:31:12 【问题描述】:

简而言之:我正在寻找一种方法来获取由ggplot2ggplotly 呈现的交互式 x/y 散点图中一系列鼠标位置(点击时)的精确坐标。

我知道plotly(以及其他几个用于 R 的交互式绘图包)可以与Shiny 结合使用,其中框选或 lazzo 选择可以返回所选子空间内所有数据点的列表。但是,在我正在分析的大多数数据集中,此列表将是巨大的,并且我需要能够以 R markdown 格式可重复地进行分析(写一些,大多小于 5-6,点坐标要多得多可读)。此外,我必须知道点击的确切位置才能在不同数据集中的相同点的多边形内提取点,因此在一个数据集中选择的点列表是没有用的。

grid 包中的grid.locator() 函数几乎可以满足我的要求(包含在 fx gglocator 中的函数),但是我希望在@987654333 呈现的交互式绘图中也有一种方法可以做到这一点@(或者可能是我不知道的其他东西?)因为数据集通常非常庞大(见下图),因此在多次分析迭代期间非常感谢能够交互式地放大和缩小。

通常我必须重新调整轴数次以模拟放大和缩小,这在多次执行时会让人筋疲力尽。正如您在上图中所见,图中有很多信息可供探索(该图在内存中约为 300MB)。

下面是我目前在静态图上使用grid.locator 的小reprex

library(ggplot2)
library(grid)

p <- ggplot(mtcars, aes(wt, mpg)) +
  geom_point()

locator <- function(p) 
  # Build ggplot object
  ggobj <- ggplot_build(p)

  # Extract coordinates
  xr <- ggobj$layout$panel_ranges[[1]]$x.range
  yr <- ggobj$layout$panel_ranges[[1]]$y.range

  # Variable for selected points
  selection <- data.frame(x = as.numeric(), y = as.numeric())
  colnames(selection) <- c(ggobj$plot$mapping$x, ggobj$plot$mapping$y)

  # Detect and move to plot area viewport
  suppressWarnings(print(ggobj$plot))
  panels <- unlist(current.vpTree()) %>%
    grep("panel", ., fixed = TRUE, value = TRUE)
  p_n <- length(panels)
  seekViewport(panels, recording=TRUE)
  pushViewport(viewport(width=1, height=1))

  # Select point, plot, store and repeat
  for (i in 1:10)
    tmp <- grid.locator('native')
    if (is.null(tmp)) break
    grid.points(tmp$x,tmp$y, pch = 16, gp=gpar(cex=0.5, col="darkred"))
    selection[i, ] <- as.numeric(tmp)
  
  grid.polygon(x= unit(selection[,1], "native"), y= unit(selection[,2], "native"), gp=gpar(fill=NA))
  #return a data frame with the coordinates of the selection
  return(selection)


locator(p)

然后从这里使用point.in.polygon 函数根据选择对数据进行子集化。

一种可能的解决方案是在绘图中添加(例如 100x100)不可见点,然后在 Shiny 应用程序中使用 event_data()plotly_click 功能,但这一点都不理想。

提前感谢您的想法或解决方案,希望我的问题足够清楚。

-- 卡斯帕

【问题讨论】:

这对您有帮助吗:shiny.rstudio.com/articles/plot-interaction.html 这正是我希望在情节或其他交互式小部件中存在的功能。我在 plotly R github repo 上发布了一个功能请求,希望尽快得到答复:github.com/ropensci/plotly/issues/1194 这是对类似问题的一个非常详细的答案,可能会有所帮助? ***.com/a/46249646/5350621 【参考方案1】:

我使用了 ggplot2。除了https://shiny.rstudio.com/articles/plot-interaction.html的资料,我想提一下:

首先,创建绘图时,不要在“renderPlot()”中使用“print()”,否则坐标会出错。例如,如果您在 UI 中有以下内容:

plotOutput("myplot", click = "myclick")

服务器中的以下内容将起作用:

output$myplot <- renderPlot(
    p = ggplot(data = mtcars, aes(x=mpg, y=hp)) + geom_point()
    p
)

但是如果你这样做,点击坐标会出错:

output$myplot <- renderPlot(
    p = ggplot(data = mtcars, aes(x=mpg, y=hp)) + geom_point()
    print(p)
)

然后,您可以通过添加到服务器来存储坐标:

mydata = reactiveValues(x_values = c(), y_values = c())

observeEvent(input$myclick, 

    mydata$x_values = c(mydata$x_values, input$myclick$x)
    mydata$y_values = c(mydata$y_values, input$myclick$y)

)

除了X-Y坐标,当你用ggplot2使用facet时,你指的是点击的facet panel by

input$myclick$panelvar1

【讨论】:

感谢您的建议。但我正在寻找让它与情节或类似的交互式可视化小部件一起使用。它仅适用于 ggplot2+shiny,但不适用于 plotly(通过 ggplotly 函数)。因此能够放大绘图,同时能够在选择中提取坐标。正如您在图中看到的那样,我必须使用它的数据类型通常有数千个点。 您可以使用ggplot添加缩放,只需查看这篇文章shiny.rstudio.com/articles/plot-interaction-advanced.html

以上是关于在交互式绘图中提取鼠标点击的精确坐标的主要内容,如果未能解决你的问题,请参考以下文章

无法在 svg 中获得鼠标指针的精确 xy 坐标(在路径标记上)

易语言,怎么对指定窗口模拟鼠标点击和按键,可以后台的

21.图形交互之tkinter--鼠标键盘位置实时获取

Qt 如何获取滚动窗体中鼠标点击的坐标

如何将鼠标点击信号连接到 pyqtgraph 绘图小部件

Cesium 获取鼠标点击坐标及世界坐标与弧度(经纬度)转换