Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add data.frame -> shinyTree helper function #8

Open
trestletech opened this issue Oct 7, 2014 · 7 comments
Open

Add data.frame -> shinyTree helper function #8

trestletech opened this issue Oct 7, 2014 · 7 comments

Comments

@trestletech
Copy link
Collaborator

From #4

It would also be nice to add a small helper function that creates a nested list object, based on a data-frame which holds the hierarchical structure of the data to be visualized by jsTree. In the end I used a bunch of lapply calls to construct a nested list object which was a bit cumbersome. I guess better alternatives exist...

More details in comments to the original issue.

@JasperSch
Copy link
Contributor

I came up with this function inspired by this discussion https://community.rstudio.com/t/how-to-recursively-apply-a-function-to-a-nested-list-of-data-frames/70324/3. I can make a PR if it looks good.

Function + MWE:

library(shiny)
library(shinyTree)

# Recursively apply function to all data frames in a nested list
dfrapply <- function(object, f, ...) {
  if (inherits(object, "data.frame")) {
    return(f(object, ...))
  }
  if (inherits(object, "list")) {
    return(lapply(object, function(x) dfrapply(x, f, ...)))
  }
  stop("List element must be either a data frame or another list")
}


#' convert a data.frame to nested list representing a tree
#' @param df data.frame or data.table
#' @param hierarchy character ordered vector of column names defining the hierarchy
#' @return nested list
dfToTree <- function(df, hierarchy){ 
  l <- df
  for(c in hierarchy){
    l <- dfrapply(
        object = l,
        f = function(x){
          split(x, x[[c]], drop = TRUE)
        }
    )
  }
  dfrapply(l, function(x){""})
}


ui <- fluidPage(shinyTree("myTree"))
server <- function(input,output,session){
  df <- data.frame(Titanic)
  tree <- dfToTree(df, c("Sex", "Class", "Survived"))
  output$myTree <- renderTree({tree})
}
shinyApp(ui,server)


@bellma-lilly
Copy link
Contributor

@JasperSch This is very nice. I would lean toward this being an example rather than a member of the package because I think often people might want to customize it (to include the column name for example).

On the other hand, if we had a dfToTree and a treeToDF, maybe it makes sense to have those as member functions.

I would like to hear what other people think, and then I hope you will move forward with a PR.

@JasperSch
Copy link
Contributor

@bellma-lilly Thank you for the feedback. Both options seem reasonable to me. I'll be glad to contribute once a decision is made.

@JasperSch
Copy link
Contributor

Regarding treeToDf, this is what I'm currently using:

# @param tree nested list
# @param hierarchy ordered character vector with column name of each level
# @return data.frame
treeToDf <- function(tree, hierarchy){
  for(column in hierarchy){
    col <- sapply(tree, names)
    col <- lapply(col, function(x){
          if(is.null(x)){
            NA
          } 
          else {
            x
          }          
        })
    col <- unlist(col)
    df[,column] <- col 
    tree <- unlist(tree, recursive = FALSE) 
  }
df
}

# in shiny:
tree <- get_selected(input$tree, format = c("slices"))
df <- treeToDf(tree, hierarchy)

@bellma-lilly
Copy link
Contributor

@JasperSch It looks like we aren't going to get a lot of feedback. I'll leave the decision to you, as it is your code. I look forward to adding it to the package. Thanks for your contribution!

@trafficonese
Copy link
Contributor

Great work @JasperSch! I think the function definitely deserves to be included in the package as I think it would be easier to transform a dataframe into the structure the function needs than to build the list itself.

So, I think it would definitely benefit most of the users, especially newcomers. If you want to create your custom list, you can still do so.

@JasperSch JasperSch mentioned this issue Oct 16, 2020
@dommens
Copy link

dommens commented Dec 2, 2020

Great work! Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants