Механизм R за вводом $ table_rows_all от DT - PullRequest
0 голосов
/ 27 августа 2018

У меня вопрос о вводе $ table_rows_all из пакета DT. Я действительно заметил, что при его использовании мой код / ​​таблица отображается более одного раза (?). Сначала таблица с 0 строками, а затем в соответствии с отфильтрованными строками -> мое реальное приложение очень сложное, поэтому я теряю время во время этой операции .

Вот простой пример того, что я имею в виду:

library(shiny)
library(DT)

ui <- bootstrapPage(
dataTableOutput("table1"),
dataTableOutput("table2"))

server <- function(input, output) {

output$table1 <- renderDataTable({
datatable(iris,filter="top")})

output$table2 <- renderDataTable({
data <- iris[input$table1_rows_all,]
str(data)
datatable(data)})
}
shinyApp(ui = ui, server = server)

После запуска этого кода мы можем увидеть в консоли вывод:

'data.frame':   0 obs. of  5 variables:
 $ Sepal.Length: num 
 $ Sepal.Width : num 
 $ Petal.Length: num 
 $ Petal.Width : num 
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 
'data.frame':   0 obs. of  5 variables:
 $ Sepal.Length: num 
 $ Sepal.Width : num 
 $ Petal.Length: num 
 $ Petal.Width : num 
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 
'data.frame':   150 obs. of  5 variables:
 $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
 $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
 $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
 $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
 $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

Я пытался найти какую-либо документацию, но ничего не смог найти. Любое объяснение будет полезным!

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

Пока @thothal предлагает решение, здесь я бы хотел прямо ответить на вопрос. Когда вы инициализируете свое приложение, DataTables просто пустые <divs>, которые заполняются содержимым только тогда, когда пользователь открывает приложение. Чтобы проверить это, запустите ваш пример, откройте его в браузере и затем (в Firefox) щелкните правой кнопкой мыши -> Просмотреть исходный код страницы. Для объяснения см. здесь .

Давайте посмотрим на это в вашем приложении - я добавил несколько «отладочных отпечатков» и предупреждение js, которое поможет:

library(shiny)
library(DT)

ui <- bootstrapPage(
  shiny::tags$script(
    "$(document).on('shiny:sessioninitialized', function(event) {
      alert('Connected to the server');
    });"
  ),
  dataTableOutput("table1"),
  dataTableOutput("table2"))

server <- function(input, output) {

  #  this ignores input$table1_rows_all being NULL and runs only when there is a value
  observeEvent(
    input$table1_rows_all,
    {
      print("observeEvent called")
      print(input$table1_rows_all)
    }
  )

  output$table1 <- renderDataTable({
    print("renderDataTable -- table 1 called")
    datatable(iris,filter="top")
  })

  output$table2 <- renderDataTable({
    print("renderDataTable -- table 2 called")
    if (is.null(input$table1_rows_all)) {
      print("input$table1_rows_all is NULL")
    }
    data <- iris[input$table1_rows_all,]
    datatable(data)
  })
}

shinyApp(ui = ui, server = server, options = list(launch.browser = FALSE))

Запустите приложение и откройте его в браузере. Вы видите, что сеанс инициализирован и каждый renderDataTable был запущен один раз. Как уже упоминалось ранее, они сейчас являются просто пустыми заполнителями, а переменная input$table1_rows_all на данный момент просто не существует - поэтому у вас 0 строк.

[1] "renderDataTable -- table 1 called"
[1] "renderDataTable -- table 2 called"
[1] "input$table1_rows_all is NULL"

Нажмите кнопку ОК, чтобы продолжить. Следующие строки печатаются впоследствии:

[1] "renderDataTable -- table 2 called"
[1] "input$table1_rows_all is NULL"
[1] "observeEvent called"
  [1]   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28
 [29]  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56
 [57]  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83  84
 [85]  85  86  87  88  89  90  91  92  93  94  95  96  97  98  99 100 101 102 103 104 105 106 107 108 109 110 111 112
[113] 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
[141] 141 142 143 144 145 146 147 148 149 150
[1] "renderDataTable -- table 2 called"

Мое понимание того, что здесь происходит, следующее:

1) почему-то вызывается функция renderDataTable для table2. Тем не менее, input$table1_rows_all по-прежнему NULL.

2) table1 фактически обрабатывается (то есть загружаются строки), поэтому input$table1_rows_all становится доступным. Это приводит к печати с observeEvent и другому вызову с renderDataTable для table2.

0 голосов
/ 20 сентября 2018

Простое req предотвращает это поведение:

library(shiny)
library(DT)

ui <- bootstrapPage(
  dataTableOutput("table1"),
  dataTableOutput("table2"))

server <- function(input, output) {

  output$table1 <- renderDataTable({
    datatable(iris,filter="top")
  })

  output$table2 <- renderDataTable({
    req(input$table1_rows_all) ## run the following code only if table1_rows_all is truthy
    data <- iris[input$table1_rows_all,]
    str(data)
    datatable(data)
  })
}
shinyApp(ui = ui, server = server)

# 'data.frame':   150 obs. of  5 variables:
#  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
#  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
#  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
#  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
#  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...

Мое понимание reactives состоит в том, что всякий раз, когда что-то изменяется, вызываются функции oberserver/render*. Я предполагаю, что это также имеет место при запуске.

Для observeEvent у вас есть даже параметр ignoreInit, который запрещает наблюдателю запускать init.

...