Home > OS >  Using rbind to append the results to a data frame in a for-loop
Using rbind to append the results to a data frame in a for-loop

Time:11-24

I'm new to Rshiny and I'm having problems displaying the results in a for-loop where all the iterations get appended into the same data frame. The below minimal example works fine in R Desktop:

df_total = data.frame()
for (i in 1:7){
  # vector output
  model <- i   10
    
    # add vector to a dataframe
    df <- data.frame(model)
  df_total <- rbind(df_total,df)
}

But when I try to replicate this in Rshiny and display the results in a table I just get blank results. Here is the minimal example of the code I'm using in Rshiny:

rm(list=ls())


library(tidyverse)
library(shiny)


ui <- fluidPage(
  
  mainPanel(
    
    #Add tabs to the Dashboard
    tabsetPanel(type = "tab",
                
                
                #for DT::dataTableOutput
                tabPanel("table1", DT::dataTableOutput("TableSample")),
    )
    
  )
)

server <- function(input, output, session) {
  

  
  FinalTable <- reactive({
    
    df_total = data.frame()
    for (i in 1:7){
      # vector output
      model <- i   10
      
      # add vector to a dataframe
      df <- data.frame(model)
      df_total <- rbind(df_total,df)
    }
    

    
  })  
  

  
  output$TableSample <- DT::renderDataTable(FinalTable(), extensions = 'Buttons', 
                                                     options = list(scrollX=TRUE, lengthMenu = c(5,10,15),
                                                                    paging = TRUE, rownames = FALSE, searching = TRUE,
                                                                    fixedColumns = FALSE, autoWidth = FALSE,
                                                                    ordering = TRUE, dom = 'tB',
                                                                    buttons = c('copy', 'csv', 'excel','pdf')))                                        
  
  

}


shinyApp(ui, server)

I have try the suggestions posted here and here.

I tried to use an observer to bind the reactive output in the for-loop. Tried several different approaches but nothing seemed to work.

CodePudding user response:

you need to add df_total to be the return of reactive FinalTable, like this :

   FinalTable <- reactive({
      
      df_total = data.frame()
      for (i in 1:7){
         # vector output
         model <- i   10
         
         # add vector to a dataframe
         df <- data.frame(model)
         df_total <- rbind(df_total,df)
      }
      df_total
      
      
   })  

CodePudding user response:

This is not an answer to your question, but I would nevertheless like to make a comment concerning a performance problem in your code. By copying the entire data frame in each iteration, your operation is quadratic in the number of rows.

Unfortunately this cannot be solved by direct assignment to a data frame row due to R's handling of reference counting (the treatment of assignment to copies) for data frames: http://adv-r.had.co.nz/memory.html (Hadley Wickham: "Advanced R").

This code becomes dramatically faster, however, if you convert the data frame to a matrix (only works when all columns are of the same type) and directly assign to the specific rows:

df_total <- matrix(nrow=..., ncol=...)
for (i in 1:N) {
  df_total[i,] <- ... # row to be added
}
as.data.frame(df_total)

If a matrix is not possible because the columns are of different types, you can use a list instead of a data frame, as explained in the "Advanced R" chapter given above.

  • Related