Измените конкретную трассировкуplotly с помощьюplotlyProxy, не ссылаясь на другие трассировки

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

library(shiny)
library(plotly)
library(purrr)

plot_cylinder <- function(x, y, z, radius, height, color = 'red') {
  theta <- seq(0, 2*pi, length.out = 30)
  z_cyl <- seq(z, z + height, length.out = 2)
  x_cyl <- outer(x + radius * cos(theta), rep(1, length(z_cyl)))
  y_cyl <- outer(y + radius * sin(theta), rep(1, length(z_cyl)))
  z_cyl <- outer(rep(1, length(theta)), z_cyl)
  
  list(
    type = "surface",
    x = x_cyl,
    y = y_cyl,
    z = z_cyl,
    colorscale = list(c(0, color), c(1, color))
  )
}

plot_sphere <- function(x, y, z, r, color = 'blue') {
  theta <- seq(0, 2*pi, length.out = 30)
  phi <- seq(0, pi, length.out = 30)
  x_sphere <- x + r * outer(cos(theta), sin(phi))
  y_sphere <- y + r * outer(sin(theta), sin(phi))
  z_sphere <- z + r * outer(rep(1, length(theta)), cos(phi))
  
  list(x = x_sphere, y = y_sphere, z = z_sphere, color = color)
}

# Static sphere data
sphere_radius <- 7.24
sphere_data <- plot_sphere(0, 0, 10, sphere_radius)

cylinder_data <- plot_cylinder(0, 0, 0, 3, 10)

ui <- fluidPage(
  titlePanel("Cylinder Plotting"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("radius", "Cylinder Radius:", min = 1, max = 10, value = 3),
      sliderInput("height", "Cylinder Height:", min = 1, max = 20, value = 10),
      actionButton("initialize", "Initialize Cylinder")
    ),
    mainPanel(
      plotlyOutput("plot")
    )
  )
)

server <- function(input, output, session) {
  
  plot <- plot_ly() |> 
    add_surface(x = sphere_data$x, y = sphere_data$y, 
                z = sphere_data$z, colors = sphere_data$color, 
                opacity = 0.5, name = "sphere") |> 
    add_surface(x = cylinder_data$x, y = cylinder_data$y, 
                z = cylinder_data$z, colorscale = cylinder_data$colorscale, 
                opacity = 0, name = "cylinder")
  
  pb <- plotly_build(plot)
  traces <- map(pb$x$data, "name")
  
  output$plot <- renderPlotly({
    plot
  })
  
  observeEvent(input$initialize, {
    proxy <- plotlyProxy("plot", session)
    
    plotlyProxyInvoke(proxy, "restyle", list(
      opacity = lapply(traces, function(name) if (name %in% "cylinder") 0.1 else 0.5)
      ))
  })
  
  observeEvent(c(input$radius, input$height), {
    proxy <- plotlyProxy("plot", session)
    
    # Get the updated cylinder trace
    cylinder_data <- plot_cylinder(0, 0, 0, input$radius, input$height)
    
    # Update the trace with the new x, y, z values
    plotlyProxyInvoke(proxy, "restyle", list(
      x = lapply(traces, function(name) if (name %in% "cylinder") cylinder_data$x else sphere_data$x),
      y = lapply(traces, function(name) if (name %in% "cylinder") cylinder_data$y else sphere_data$y),
      z = lapply(traces, function(name) if (name %in% "cylinder") cylinder_data$z else sphere_data$z)
    ))
  })
}

shinyApp(ui = ui, server = server)

Я не вижу, где в вашем коде определяется traces. Я пропустил это?

Stéphane Laurent 31.05.2024 10:10

извинения; исправленный

its.me.adam 31.05.2024 14:16

Если я правильно понял, вы хотели бы изменить трассировку по ее имени? Вот как получить сопоставление трассировки.имя/трассировка.индекс.

ismirsehregal 31.05.2024 15:04

@ismirsehregal Похоже, некоторые пакеты изменились, и эти ответы устарели. Но чем могут помочь индексы? Могу ли я сделать plotlyProxyInvoke(proxy, "restyle", indices, x ...?

its.me.adam 31.05.2024 21:28

Да, функция изменения стиляplotly имеет параметр traceIndices. Сейчас у меня мало времени, но я постараюсь вернуться сюда, чтобы дать правильный ответ.

ismirsehregal 01.06.2024 08:07

Итак, выше я привожу только список для параметра «обновление». Вместо этого я могу предоставить более простой список и еще один список индексов трассировки.

its.me.adam 04.06.2024 05:08

Точно, я оставил пример ниже.

ismirsehregal 04.06.2024 10:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
7
87
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Функция изменения стиля Plotly имеет параметр traceIndices:

Эффективное средство изменения атрибутов массива данных в существующий сюжет. При рестайлинге вы можете выбрать указанный изменения затрагивают столько трасс, сколько необходимо. Обновление предоставляется в виде отдельный объект и затронутые следы представлены в виде списка отслеживает индексы. Обратите внимание: если оставить индексы трассировки неуказанными, это предполагает что вы хотите изменить стиль всех трассировок.

Вот как обновить только данные первой трассировки (индекс: 0) с помощью plotlyProxyInvoke:

library(shiny)
library(plotly)
library(purrr)

plot_cylinder <- function(x, y, z, radius, height, color = 'red') {
  theta <- seq(0, 2*pi, length.out = 30)
  z_cyl <- seq(z, z + height, length.out = 2)
  x_cyl <- outer(x + radius * cos(theta), rep(1, length(z_cyl)))
  y_cyl <- outer(y + radius * sin(theta), rep(1, length(z_cyl)))
  z_cyl <- outer(rep(1, length(theta)), z_cyl)
  
  list(
    type = "surface",
    x = x_cyl,
    y = y_cyl,
    z = z_cyl,
    colorscale = list(c(0, color), c(1, color))
  )
}

plot_sphere <- function(x, y, z, r, color = 'blue') {
  theta <- seq(0, 2*pi, length.out = 30)
  phi <- seq(0, pi, length.out = 30)
  x_sphere <- x + r * outer(cos(theta), sin(phi))
  y_sphere <- y + r * outer(sin(theta), sin(phi))
  z_sphere <- z + r * outer(rep(1, length(theta)), cos(phi))
  
  list(x = x_sphere, y = y_sphere, z = z_sphere, color = color)
}

# Static sphere data
sphere_radius <- 7.24
sphere_data <- plot_sphere(0, 0, 10, sphere_radius)

cylinder_data <- plot_cylinder(0, 0, 0, 3, 10)

ui <- fluidPage(
  titlePanel("Cylinder Plotting"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("radius", "Cylinder Radius:", min = 1, max = 10, value = 3),
      sliderInput("height", "Cylinder Height:", min = 1, max = 20, value = 10)
    ),
    mainPanel(
      plotlyOutput("plot")
    )
  )
)

server <- function(input, output, session) {
  
  plotly_object <- plot_ly(colors = sphere_data$color) |> 
    add_surface(x = cylinder_data$x, y = cylinder_data$y, 
                z = cylinder_data$z, colorscale = cylinder_data$colorscale, 
                opacity = 0.5, name = "cylinder") |>
    add_surface(x = sphere_data$x, y = sphere_data$y, 
                z = sphere_data$z,
                opacity = 0.5, name = "sphere")
  
  pb <- plotly_build(plotly_object)
  traces <- unlist(map(pb$x$data, "name"))
  trace_indices <- setNames(seq_along(traces) - 1L, traces)
  
  output$plot <- renderPlotly({
    plotly_object
  })
  
  observeEvent(c(input$radius, input$height), {
    proxy <- plotlyProxy("plot", session)
    
    # Get the updated cylinder trace
    cylinder_data <- plot_cylinder(0, 0, 0, input$radius, input$height)
    # Update the trace with the new x, y, z values
    plotlyProxyInvoke(proxy, "restyle", list(
      x = list(cylinder_data$x),
      y = list(cylinder_data$y),
      z = list(cylinder_data$z)
    ), trace_indices[["cylinder"]])
    # if you need to modify multiple traces at once (and leave others as they are):
    # plotlyProxyInvoke(proxy, "restyle", list(
    #   x = list(cylinder_data$x, sphere_data$x + 100L),
    #   y = list(cylinder_data$y, sphere_data$y + 100L),
    #   z = list(cylinder_data$z, sphere_data$z + 100L)
    # ), list(0L, 1L))
  })
}

shinyApp(ui = ui, server = server)

Можете ли вы добавить индекс к сопоставлению имен трассировок из ответа , который вы предоставили выше? У меня много трасс, поэтому я не могу выбрать их просто по номеру, например 0L.

its.me.adam 04.06.2024 14:40

Просто используйте подход plotly_build, показанный в вашем примере. Пожалуйста, посмотрите мое редактирование.

ismirsehregal 04.06.2024 14:57

Спасибо! Как бы вы подошли к этому в случае, если plotly_build не возвращает все следы? В частности, те, которые добавлены с plotlyProxyInvoke("addTraces"?

its.me.adam 04.06.2024 16:46

Для динамического обновления сопоставления имени трассировки/индекса трассировки потребуется обновленное решение JS (в вашем примере это не обязательно). Я еще не знаю. Я обновлю свой предыдущий ответ, как только у меня будет решение. Не уверен, когда у меня будет время снова покопаться в этом.

ismirsehregal 04.06.2024 20:49

@its.me.adam Я только что обновил свой предыдущий ответ, добавив другой подход к извлечению имени трассировки/сопоставлению индекса трассировки.

ismirsehregal 05.06.2024 11:21

Другие вопросы по теме