Нарисуйте ggplot для изменения реактивного значения в фоновом режиме, на несфокусированных вкладках - PullRequest
0 голосов
/ 06 июня 2018

Цель

Увеличение текучести UX за счет уменьшения времени ожидания.

Проблема

Я создаю панель исследования данных,Существует две вкладки: 1) (вкладка по умолчанию) - вкладка с отображением данных и 2) вкладка с отображением ggplots.Пользователь может изучить данные, выбрав параметры на боковой панели (например, выбрать, сколько точек вы хотите отобразить).Таблица реагирует на изменения после изменения, но ggplot на другой вкладке - нет, пока вкладка не выбрана, только тогда ggplot будет нарисован .

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

То, что я пробовал

Я попытался просмотреть SO и Google для намеков на эту проблему, но я не должен искать правильно, так как это, казалось бы, легкая проблема.Я думал о реализации функции, которая переключается на каждую несфокусированную вкладку в течение доли секунды после того, как указано значение для принудительного рисования, но это UX не дружелюбно и невероятно хакер для такой маленькой проблемы.

MCVE

# Load libraries
library(shiny)
library(shinydashboard)
library(DT)
library(ggplot2)
library(ggthemes)

# Set seed to arbitrary value for reproducibility
set.seed(1)

# Create random dataset of 100K points
test.df <- data.frame(a = 1:100000, b = rnorm(n = 100000, mean= 2, sd=1))

# Create ui
ui <- dashboardPage(dashboardHeader(),
                    dashboardSidebar(
                      sidebarMenu(
                        id = "tabs",
                        # Tab to show table
                        menuItem("Tab 1", tabName = "item1"),
                        # Tab to show plot
                        menuItem("Tab 1", tabName = "item2"),
                        numericInput("numeric", "Length of data", value = 1)
                    )),
                    dashboardBody(
                      tabItems(
                        tabItem("item1", dataTableOutput("table")),
                        tabItem("item2", plotOutput("plot"))
                      )
                    )
                  )

server <- function(input, output) {

  # Get first n rows
  test.df.sample <- reactive({
    head(test.df, n=input$numeric)
  })

  # Render table
  output$table <- DT::renderDataTable({
    datatable(test.df.sample())
  })

  # Render ggplot
  output$plot <-  renderPlot({
    ggplot(test.df.sample()) +
      geom_point(aes(x=a, y=b)) +
      theme_tufte()
  })
}

shinyApp(ui = ui, server = server)

Обновление прогресса

Обновление 1 - Дата публикации + 2

Под давлением времени я решилреализовать хакерский метод создания вызова updateTabItems () для мгновенного переключения между вкладками.Этот метод работает, так как он вызывает блестящее обновление каждого содержимого tabItem, но оставляет нежелательные визуальные эффекты (например, я использую googleway для построения карты, но он масштабируется на максимальном уровне, поэтому вы видите полосу, где карта мира повторяется 4 раза, если он обновляется этим хакерским методом)

1 Ответ

0 голосов
/ 09 июня 2018

Я думаю, вы могли бы использовать опцию suspendWhenHidden из outputOptions, чтобы получить поведение, которое вы ищете.Однако этого недостаточно, поскольку для этого пользователю необходимо будет один раз инициализировать график, перейдя на вторую вкладку.Мы можем решить эту проблему, установив для высоты и ширины графика ненулевые значения, см. здесь .

Обратите внимание, что теперь таблица отображается только тогда, когда таблица и графикзакончено рендеринг, так что это займет немного больше времени.Таким образом, пользователь должен ждать один раз в течение 60 секунд вместо того, чтобы ждать 10 секунд шесть раз.Преимущество нового поведения заключается в том, что, по крайней мере, пользователь может получить чашку кофе и знает, что все готово для просмотра, когда он вернется.Я надеюсь, что это было ваше желаемое поведение.Если ваша цель состояла в том, чтобы сделать все последовательно - я не уверен, что это возможно с Shiny, я боюсь ...

Рабочий пример приведен ниже, надеюсь, это поможет!

# Load libraries
library(shiny)
library(shinydashboard)
library(DT)
library(ggplot2)
library(ggthemes)

# Set seed to arbitrary value for reproducibility
set.seed(1)

# Create random dataset of 100K points
test.df <- data.frame(a = 1:100000, b = rnorm(n = 100000, mean= 2, sd=1))

# Create ui
ui <- dashboardPage(dashboardHeader(),
                    dashboardSidebar(
                      sidebarMenu(
                        id = "tabs",
                        # Tab to show table
                        menuItem("Tab 1", tabName = "item1"),
                        # Tab to show plot
                        menuItem("Tab 1", tabName = "item2"),
                        numericInput("numeric", "Length of data", value = 1)
                      )),
                    dashboardBody(
                      tabItems(
                        tabItem("item1", dataTableOutput("table")),
                        tabItem("item2", plotOutput("plot"))
                      )
                    )
)

server <- function(input, output) {

  # Get first n rows
  test.df.sample <- reactive({
    head(test.df, n=input$numeric)
  })

  # Render table
  output$table <- DT::renderDataTable({
    datatable(test.df.sample())
  })

  # Render ggplot
  output$plot <-  renderPlot({
    ggplot(test.df.sample()) +
      geom_point(aes(x=a, y=b))
    }, height = 450, width = 800)
  outputOptions(output, "plot", suspendWhenHidden = FALSE)
}

shinyApp(ui = ui, server = server)
...