Consider The following R code, I am trying to filter a dataframe by the current state of a sunburst plot in a shiny structure. This is my try:
library(shiny);library(dplyr); library(DT);library(plotly)
DF <- data.frame(x=rep(LETTERS[1:2],each=4),
y=rep(letters[3:4],each=2,length=8),
z=rep(letters[5:6],length=8),
fn=c(108, 143, 102, 300, 320, 500, 37, 90))
as.sunburstDF <- function(DF, value_column = NULL, add_root = FALSE){
require(data.table)
colNamesDF <- names(DF)
if(is.data.table(DF)){
DT <- copy(DF)
} else {
DT <- data.table(DF, stringsAsFactors = FALSE)
}
if(add_root){
DT[, root := "Total"]
}
colNamesDT <- names(DT)
hierarchy_columns <- setdiff(colNamesDT, value_column)
DT[, (hierarchy_columns) := lapply(.SD, as.factor), .SDcols = hierarchy_columns]
if(is.null(value_column) && add_root){
setcolorder(DT, c("root", colNamesDF))
} else if(!is.null(value_column) && !add_root) {
setnames(DT, value_column, "values", skip_absent=TRUE)
setcolorder(DT, c(setdiff(colNamesDF, value_column), "values"))
} else if(!is.null(value_column) && add_root) {
setnames(DT, value_column, "values", skip_absent=TRUE)
setcolorder(DT, c("root", setdiff(colNamesDF, value_column), "values"))
}
hierarchyList <- list()
for(i in seq_along(hierarchy_columns)){
current_columns <- colNamesDT[1:i]
if(is.null(value_column)){
currentDT <- unique(DT[, ..current_columns][, values := .N, by = current_columns], by = current_columns)
} else {
currentDT <- DT[, lapply(.SD, sum, na.rm = TRUE), by=current_columns, .SDcols = "values"]
}
setnames(currentDT, length(current_columns), "labels")
hierarchyList[[i]] <- currentDT
}
hierarchyDT <- rbindlist(hierarchyList, use.names = TRUE, fill = TRUE)
parent_columns <- setdiff(names(hierarchyDT), c("labels", "values", value_column))
hierarchyDT[, parents := apply(.SD, 1, function(x){fifelse(all(is.na(x)), yes = NA_character_, no = paste(x[!is.na(x)], sep = ":", collapse = " - "))}), .SDcols = parent_columns]
hierarchyDT[, ids := apply(.SD, 1, function(x){paste(x[!is.na(x)], collapse = " - ")}), .SDcols = c("parents", "labels")]
hierarchyDT[, c(parent_columns) := NULL]
return(hierarchyDT)
}
ui <- fluidPage(
mainPanel(
fluidRow(
column(width = 4,plotlyOutput("distPlot"))
,
column(width = 4, DT::DTOutput("dt_f"))
,
column(width = 4,DT::DTOutput("dt_f_sb"))
)
,
fluidRow(
column(width = 4,htmlOutput("hoverDataOut"))
,
column(width = 4,htmlOutput("clickDataOut"))
)
)
)
server <- function(input, output) {
output$dt_f <- renderDT({
#browser()
event_data <- event_data(event = "plotly_sunburstclick", source = "sunSource", priority = "event")
DF_SB <- as.sunburstDF(DF)
#browser()
ids_1 <- DF_SB[event_data$pointNumber, ]$ids
ret = tryCatch({
filtered_df <- DF
str=stringr::str_split(ids_1," - ")[[1]]
for(i in 1:length(str)){
filtered_df<-filtered_df %>% filter(.[[i]] == str[i])
}
filtered_df
}, error = function(error_condition) {
DF
})
return(ret)
})
output$dt_f_sb <- renderDT({
# generate bins based on input$bins from ui.R
as.sunburstDF(DF)
})
output$distPlot <- renderPlotly({
# generate bins based on input$bins from ui.R
plot_ly(data = as.sunburstDF(DF, value_column = "fn", add_root = TRUE),
ids = ~ids, labels= ~labels, source = "sunSource",
parents = ~parents, values= ~values,
type='sunburst', branchvalues = 'total')
})
hoverData <- reactive({
currentEventData <- unlist(event_data(event = "plotly_hover", source = "sunSource", priority = "event"))
})
clickData <- reactive({
currentEventData <- unlist(event_data(event = "plotly_sunburstclick", source = "sunSource", priority = "event"))
})
output$hoverDataOut <- renderText({
paste("Hover data:", paste(names(hoverData()), unlist(hoverData()), sep = ": ", collapse = " | "))
})
output$clickDataOut <- renderText({
paste("Click data:", paste(names(clickData()), unlist(clickData()), sep = ": ", collapse = " | "))
})
}
shinyApp(ui = ui, server = server)
It track click event and get the parents in “str” variable and try to filter the dataframe based on it! But unfortunately
It does not work perfectly when draw back. How to fix it?