Интерактивное построение с использованием растрового растра R: значения для мыши

Я хотел бы сделать небольшую программу в R для интерактивной визуализации и модификации некоторых растровых наборов данных, рассматриваемых как цветные изображения. Пользователь должен открыть файл (с терминала он ОК), занести его в график, выбрать точки для редактирования с помощью щелчков мыши и вставить новые значения.

До сих пор я так легко достигал. Я использую функцию plot() из пакета raster для визуализации графика, затем click(), чтобы выбрать точки и изменить их значение через терминал.

Я хотел бы добавить возможность показывать значения мыши. Я искал способы, как это сделать, но это не представляется возможным со стандартными пакетами R. Правильно ли это?

В этом случае я могу быть вынужден использовать внешние пакеты, такие как gGobi, iPlots, Shiny или Plotly. Тем не менее, я бы предпочел KISS и использовать только "стандартные" графические инструменты, такие как растровая функция plot() или, может быть, решетка графических объектов (например, от rasterVis).

Я понимаю, что приложение Shiny, вероятно, будет лучше, но для изучения и совершенствования требуется много времени.

Ответ 1

С помощью leaflet и mapview вы можете добиться чего-то подобного:

library(raster)
library(mapview)
library(leaflet)

f <- system.file("external/test.grd", package="raster")
r <- raster(f)

leaflet() %>% 
  addRasterImage(r, layerId = "values") %>% 
  addMouseCoordinates() %>%
  addImageQuery(r, type="mousemove", layerId = "values")

Поместив это в блестящее приложение, вы получите:

library(raster)
library(mapview)
library(leaflet)
library(shiny)

f <- system.file("external/test.grd", package="raster")
r <- raster(f)

ui <- fluidPage(
  leafletOutput("map")
)

server <- function(input, output){
  output$map <- renderLeaflet({
    leaflet() %>% 
      addRasterImage(r, layerId = "values") %>% 
      addMouseCoordinates() %>%
      addImageQuery(r, type="mousemove", layerId = "values")
  })
}

shinyApp(ui, server)

Следующий пример иллюстрирует идею преобразования растра в простые объекты/шейп файлы. Его нельзя использовать для больших файлов, но метки могут быть разработаны индивидуально, данные доступны для редактирования и могут быть легко показаны в таблице.

library(raster)
library(leaflet)
library(shiny)
library(sf)
library(DT)
library(dplyr)

## DATA
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
r1 = aggregate(r, 30)

sp = st_as_sf(rasterToPolygons(r1))
cn = st_coordinates(st_transform(st_centroid(sp),4326))
sp = st_transform(sp, 4326)
sp = cbind(sp, cn)
sp$id <- 1:nrow(sp)
colnames(sp)[1] <- "value"


## UI
ui <- fluidPage(
  leafletOutput("map"),
  uiOutput("newValueUI"),
  textInput("newVal", label = "Enter new value"),
  actionButton("enter", "Enter new value"),
  hr(),
  dataTableOutput("table")
)


## SERVER
server <- function(input, output){

  ## Reactive Shapefile
  sp_react <- reactiveValues(sp = sp)

  ## Leaflet Map
  output$map <- renderLeaflet({
    pal= colorNumeric(topo.colors(25), sp_react$sp$value)
    leaflet() %>% 
      addPolygons(data = sp_react$sp, label= paste(
        "Lng: ", as.character(round(sp_react$sp$X,4)),
        "Lat: ", as.character(round(sp_react$sp$Y,4)),
        "Val: ", as.character(round(sp_react$sp$value,4))),
        color = ~pal(sp_react$sp$value), 
        layerId = sp_react$sp$id
      )
  })

  ## Observe Map Clicks
  observeEvent(input$map_shape_click, {

    click_id = input$map_shape_click$id

    click_grid <- sp_react$sp[sp_react$sp$id == click_id,]

  })

  ## Observe Action Button
  observeEvent(input$enter, {
    click_id <- input$map_shape_click$id
    sp_react$sp[sp_react$sp$id == click_id,]$value <- as.numeric(input$newVal)
  })

  ## Data Table
  output$table <- DT::renderDataTable({
    sp_react$sp %>% st_set_geometry(NULL) %>% 
      dplyr::select(id,X,Y,value)
  })
  proxy = dataTableProxy('table')

  ## Table Proxy
  observeEvent(input$map_shape_click$id, {
    req(input$map_shape_click$id)
    proxy %>% selectRows(as.numeric(input$map_shape_click$id))
  })
}

shinyApp(ui, server)

Ответ 2

Я приведу простой пример того, как сделать это в R без внешних библиотек Java, если вы хотите использовать функции Javan, вы можете адаптировать их, но каждая графическая библиотека Java отличается от других, и я никогда не делал ничего подобного.

set.seed(123)
mydata <- data.frame(x = runif(10), y = runif(10))

edit_plot <- function(data) {
  plot(data)

  sel <- locator(n = 1)
  if(is.null(sel)) return(TRUE)
  dd <- (data$x - sel$x)^2 + (data$y - sel$y)^2

  data[which.min(dd),] <- edit(data[which.min(dd),])
  r <- edit_plot(data)
  if(r) return(TRUE)
}
edit_plot(mydata)

Для выхода нажмите Esc, когда локатор активен.