Split data.frame function by field

,

I have a data frame function whose output is too lengthy which is being used as an output in a r shiny app. I want to spilt this by field fac. How could I do it. So I want tables which has fac= A and so on for the unique fields in fac. Thank you.

prod()
   x  y fac
1  1  1   C
2  1  2   B
3  1  3   B
4  1  4   B
5  1  5   A
6  1  6   B
7  1  7   B
8  1  8   C
9  1  9   C
10 1 10   C

Assuming the output is a reactive data.frame you could split into a list of tables by fac which can be easily extracted as follows:

lst <- reactive({split(prod(), f = prod()$fac)})

# Extract each table
A <- lst()[["A"]]

Hope this helps!

Thanks @DillonHammill . This would be a static approach. How can I get the tables extracted considering I dont know the levels of factor in prod.

Do you need to iterate through each table, or find a specific one?

You can iterate through each table like this:

for (i in 1:length(lst)) {
  lst[[i]] 
  // do something
}

When I do this i get an error :

ERROR: 4 arguments passed to 'for' which requires 3

 for (i in 1:length(lst)) {
              i4imisc::add_table(
                theme_ds(
                 lst()[[i]],
                  size = 8,
                  caption =lst()[[i]],
                 footer = next_prod_use_y_foot
                )
              )  }

What might be wrong here.

lst would also be reactive as it takes on the reactive prod().

I think you need brackets after lst in your loop statement:

for(i in 1:length(lst()){
}

You could also use an apply family function (e.g. lapply) instead of loops to apply a function over your list elements.

1 Like

@DillonHammill I did fix that but still getting an error

lst <-
    reactive({
      split(next_prod_use(), f = next_prod_use()$Category)
    })


   for (i in 1:length(lst())) {
              i4imisc::add_table(
                theme_ds(
                 lst()$Category[i],
                  size = 8
                )
              )}%>%

I am not familiar with the i4imisc package so I can't comment on that, but how are you saving the output of the loop? You may need to construct an empty list and fill it as you loop through lst. Printing this list may reveal the problem.

I am not sure whether lst()$Category[i] is what you need or lst()[[i]]$Category...

assuming you want all of these tables to be rendered dynamically based on the number of different fac levels, you could use map (which is essentially, an efficient for loop) along with renderTable, renderUI and tableOutput:

You will need to load dplyr and purrr packages for the filter and map functions, respecitvely.

server.r

levels <- reactive({unique(prod()$fac})

observe({
  map(levels(), ~{
    output_name <- paste0("table_", .x)
    output[[output_name]] <- renderTable(
      prod() %>% filter(fac == .x)
    )
  })
})

output$table_ui_render <- renderUI({
  table_list <- map(levels(), ~{
      tableOutput(
        outputId = paste0("table-", .x)
      )
    }
  )

  return(tagList(table_list))
})

ui.r

uiOutput("table_ui_render")
2 Likes