Search code examples
rggplot2graph

How to replace NULL in dataframe with 0?


I have a program that allows users to import .csv file, and select axes to graph from that file. The program works when the data contains all numeric numbers; however, when there are NULL values, I get the following error: Can't combine length and colors .

An example of data I am having trouble with is included below:

length y time colors
5 0 30 NULL
10 1 60 NULL
15 2 90 NULL

If I remove the colors column, the program will work fine, so I know the program will work if there are only numbers. I think I would need to use a replace() function.

library(shiny)#load and attach package shiny
library(shinythemes)
library(data.table)
library(ggplot2)
library(tidyverse)

not_sel <- "Not selected"

main_page <- tabPanel(#create a tab panel for main_page
  title = "Data Plotter",#main_page tab titled Plot
  titlePanel("Data Plotter"),#panel titled Plot
  sidebarLayout( #create a layout with a sidebar and main area
    sidebarPanel(#side panel = inputs
      title = "Inputs",
      fileInput("csv_input","Select CSV File",accept = ".csv"),#first parameter is ID to call in server, text that appears, condition to accept
      selectInput("x_axis","Select x-axis",choices = c(not_sel)),#creates input in Inputs
      selectInput("y_axis","Select y-axis",choices = c(not_sel), selected = not_sel, multiple = TRUE),
      actionButton("run_button","Apply Changes",icon = icon("play")), #adds play icon
    ),
    mainPanel(#main panel are outputs
      tabsetPanel(#can divide output into separate viewable screens
        tabPanel(#first screen called Plot
          title = "Plot",
          plotOutput("plot_1") #make Plot screen output image
        )
      )
    )
  )
)
about_page <- tabPanel(
  title = "About",
  titlePanel("About"),#create a panel containing an application title
  "Created by NC",
  br(),#new line
  "June 2024"
)

ui <- navbarPage(#create a page with a top level navigation bar
  title = "Data Plotter",
  theme = shinytheme('sandstone'),
  main_page,
  about_page
)

server <- function(input, output){
  options(shiny.maxRequestSize=100*1024^2)
  
  data_input <- reactive({ #wraps following expression as reactive, meaning result changes over time
    req(input$csv_input)#req ensures there is csv input, otherwise does not run
    fread(input$csv_input$datapath)#fast reads input$csv$data path, which is file pathway
  })
  
  data_input_long <- reactive({
    pivot_longer(setDF(data_input()), cols = -y, names_to = "Tag", values_to = "Values")
  })
  
  data_filtered <- eventReactive(input$run_button,{
    filter(data_input_long(), Tag %in% input$y_axis)
  })
  
  observeEvent(data_input(),{#wraps code and allows it to run when specific reactive expression changes
    choices <- c(not_sel,names(data_input()))#create variable "choices", with not_sel at top and the names of data table next
    updateSelectInput(inputId = "x_axis", choices = choices)#updates the selectinput, which in turn changes the choices
    updateSelectInput(inputId = "y_axis", choices = choices)
  })
  
  output$plot_1 <- renderPlot({
    ggplot(data_filtered(), aes(x = .data[[input$x_axis]], y = Values, color = Tag))+
      geom_point()
  }) #assigns renderPlot to output, renders graph for plot_1
}

shinyApp(ui = ui, server = server)#creates Shiny application, user interface is layout of app, server is connection between input and output


Solution

  • In your data_input reactive function you can replace all NULL values with 0 as follows:

    data_input <- reactive({
      req(input$csv_input) # req ensures there is csv input, otherwise does not run
      dt <- fread(input$csv_input$datapath, na.strings = c("NULL", "")) # fast reads input$csv$data path, which is file pathway
      dt[is.na(dt)] <- 0 # replace NA values (including "NULL" strings) with 0
      dt
    })
    

    Here, na.strings = c("NULL", "") in fread specifies that both "NULL" and empty strings should be treated as NA. Then, the dt[is.na(dt)] <- 0 line replaces all NA values in the data table with 0.

    I am unable to test at the moment, but I'm sure this should work