7
votes

I want to display a table showing duplicate count along with the user defined columns. I have selectinput option in the shiny app by which the user can select multiple columns to check duplicate combinations.

But when the user selects first column, incorrect column name is displayed. when two columns are selected, the column names are correct.

Please help me to find a solution for this issue. When user selects first column, correct column should be displayed.

code,

library(shiny)
library(shinydashboard)

ui <- dashboardPage(skin = "black",
                    dashboardHeader(title = "test"),
                    dashboardSidebar(
                      sidebarMenu(
                        menuItem("Complete", tabName = "comp"))),
                  dashboardBody(useShinyjs(),
                    tabItems(
                    tabItem(tabName = "comp",
                      fluidRow(
                      box(selectInput("dup_var", "Variable", multiple = TRUE, c("1"="1","2"="2")), 
                          width = 3, status = "primary")),
                      fluidRow(
                      box(title = "Duplicate Records", width = 12, solidHeader = TRUE, status = "primary", 
                      collapsible = TRUE, DT::dataTableOutput("dup_data")))))))

server <- function(input, output, session) {
  observe({
    cname <- c("Select All", names(mtcars))
    col_options <- list()
    col_options[ cname] <- cname

    updateSelectInput(session, "dup_var",
                      label = "",
                      choices = c("Choose Attributes"="",col_options))   
  })

  output$dup_data <- DT::renderDT({ 
    if (input$dup_var == "Select All"){
      col_names = colnames(mtcars)
      df = count(mtcars, col_names)
      df = df[df$freq > 1,]
      Dup <- df$freq
      df1 <- cbind.data.frame(Dup, df[,!names(df) %in% "freq"])
      df1 <- df1[order(-df1$Dup),]
      names(df1)[names(df1) == 'Dup'] <- 'Duplicate Count'

      dp <- DT::datatable(df1, rownames = FALSE)
      return(dp)
    } else {
      col_names = colnames(mtcars[,c(input$dup_var)])
      df = count(mtcars[,c(input$dup_var)], col_names)
      df = df[df$freq > 1,]
      Dup <- df$freq
      df1 <- cbind.data.frame(Dup, df[,!names(df) %in% "freq"])
      df1 <- df1[order(-df1$Dup),]
      names(df1)[names(df1) == 'Dup'] <- 'Duplicate Count'

      dp <- DT::datatable(df1, rownames = FALSE)
      return(dp)
    }
  }) 
          }
shinyApp(ui, server)

incorrect column name correct column name

Thanks in Advance.

2

2 Answers

2
votes

It looks like you miss a few drop = FALSE. Adding this, you can handle the special case of one column the same way as the cases with multiple columns:

else {
  col_names = colnames(mtcars[, c(input$dup_var), drop = FALSE])
  df = count(mtcars[, c(input$dup_var), drop = FALSE], col_names)
  df = df[df$freq > 1, ]
  Dup <- df$freq
  df1 <- cbind.data.frame(Dup, df[, !(names(df) %in% "freq"), drop = FALSE])
  df1 <- df1[order(-df1$Dup), ]
  names(df1)[names(df1) == 'Dup'] <- 'Duplicate Count'

Note that I am not sure about your function count, but the above seems plausible to me.

0
votes

You do not need to put an if-else statement inside the output because subsetting the data frame by column will give you the values you need here. I could not completely reproduce your code, and maybe this give you an idea.

library(shiny)

choices <- c("Select All", names(mtcars))

ui <- fluidPage(
  selectInput("dup_var", "Variable", choices, multiple = TRUE),
  DT::dataTableOutput("dup_data")
)

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

  observe({
    if ("Select All" %in% input$dup_var) {
      allchoices <- setdiff(choices, "Select All")
      updateSelectInput(session, "dup_var", selected = allchoices)
    }
  })

  output$dup_data <- DT::renderDataTable({
    data <- mtcars[input$dup_var]
    do.call(rbind, lapply(names(data), function(name) {
      x <- data[, name, drop = TRUE]
      aggregate(list(count = x), by = list(name = x), length)
    })) -> df

    df <- df[df$count > 1, ]
    data.frame(duplicate_count = df$count, x = df[,!names(df) %in% "count"],
               stringsAsFactors = FALSE)
  }, rownames = FALSE)
}

shinyApp(ui, server)