Reta
Reta

Reputation: 383

"cannot coerce type 'closure' to vector of type 'character'" error when trying to convert date column

I'm hoping someone can help me to figure out the issue with my code. I'm trying to figure out the issue with my code for like 5 hours and checked these links 1,2 but couldn't figure out the issue with my code I'm trying to build a Shiny app but when I run my code, I keep getting the error message:

Error: Problem with `mutate()` column `Date`.
ℹ `Date = ymd(Date)`.
x cannot coerce type 'closure' to vector of type 'character'

It looks like the issue is with creating the columns Date and Month but I have them in my data as you can see in this snapshot of my data :

enter image description here

This is my code for reading my data and wrangle data

#Read and wrangle data 
dvc_read <- st_read("/Users/Desktop/shap/accident_data.shp",  # shapefile stored in repo
  stringsAsFactors = FALSE  # read factor columns as character columns
) 


dvc_wrangle <- dvc_read %>% 
  st_transform(crs = 4326) %>%  # transform coords to latlong
  # decapitalise everything for easy handling
  rename_all(tolower) %>% 
  mutate_if(is.character, tolower) %>%  # simplify strings
  # deal with dates
  mutate(
    Date = ymd(Date), # the issue is with line 
    Month = case_when( # and this line
      Month == 1 ~  "Jan", Month == 2 ~  "Feb",
      Month == 3 ~  "Mar", Month == 4 ~  "Apr",
      Month == 5 ~  "May", Month == 6 ~  "Jun",
      Month == 7 ~  "Jul", Month == 8 ~  "Aug",
      Month == 9 ~  "Sep", Month == 10 ~ "Oct",
      Month == 11 ~ "Nov", Month == 12 ~ "Dec",
      TRUE ~ "Unknown"
    ),
    # clean up strings (not perfect)
    Severity = if_else(Severity %in% c("1", "2", "3"), "unknown", Severity),
    Accident.Description = if_else(Accident.Description == "Road closed", "Road_closed", Accident.Description),
    City = if_else(str_detect(City, "x") == TRUE, "unknown", City),
    City = if_else(
      City %in% c(
        "Brooklyn", "Jamaica", "Merrick", "Roosevelt", "unclassified",
      ), "unknown", City
    ),
    # final name tidy-up
    Accident.Description = str_replace_all(Accident.Description, "_", " ")
  ) %>% 
  # title case for these columns
  mutate_at(vars(Severity, Accident.Description, City), tools::toTitleCase) # To Title Case


###
# extract latlong cols from sf geometry and bind back to df
dvc_xy <- as.data.frame(st_coordinates(dvc_wrangle))
dvc <- bind_cols(dvc_wrangle, dvc_xy) %>% rename(latitude = X, longitude = Y)
saveRDS(dvc,"/Users/Desktop/shap/dvc.RDS")
dvc <- readRDS("data/dvc.RDS")

# Month order for dropdown input
mo_order <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")

I'll add the Ui code and the server code just for a better understanding

The UI code:

ui <- dashboardPage(

  dashboardHeader(
    
    title = "Title",
    titleWidth = 450
  ),  # end dashboardHeader()
  
  dashboardSidebar(
    HTML("<br>"),
    
    box(
      title = "Filters",
      width = 12,
      background = "blue",
      collapsible = TRUE, collapsed = FALSE,
      selectInput(
        inputId = "input_year", 
        label = "Year",
        choices = sort(unique(dvc$Year)),
        multiple = TRUE,
        selected = sample(unique(dvc$Year), 1)
      ),
      selectInput(
        inputId = "input_month", 
        label = "Month",
        choices = unique(dvc$Month[order(match(dvc$Month, mo_order))]),
        multiple = TRUE,
        selected = sample(unique(dvc$Month), 3)
      ),
      selectInput(
        inputId = "input_la", 
        label = "Accident.Description",
        choices = sort(unique(dvc$Accident.Description)),
        multiple = TRUE,
        selected = sample(unique(dvc$Accident.Description), 3)
      )
    )  # end box()
  ),  # end dashboardSidebar()
  
  dashboardBody(
    
    fluidRow(
      valueBoxOutput("output_valueselection"),
      valueBoxOutput("output_valueyearla"),
      valueBoxOutput("output_valueyear"),
      tabBox(
        id = "tabset1",
        width = 12,
        tabPanel("Map", leafletOutput("output_map", height = "600px")),
        tabPanel("Table", dataTableOutput("output_table"))
      )
    )  # end fluidRow()
  )  # end dashboardBody()
  
)  # end of ui dashboardPage()

The server code:

server <- function(input, output) {
  
  # Value box - year
  output$output_valueyear <- renderValueBox({
    shinydashboard::valueBox(
      value = dvc %>% st_drop_geometry() %>% filter(Year %in% input$input_year) %>% count() %>% pull(),
      subtitle = "Collisions in selected year(s)",
      icon = icon("calendar", lib = "font-awesome"),
      color = "blue",
      width = 4
    )
  })  # end of renderValueBox
  
  # Value box - year by la
  output$output_valueyearla <- renderValueBox({
    shinydashboard::valueBox(
      value = dvc %>% st_drop_geometry() %>% filter(Year %in% input$input_year, Accident.Description %in% input$input_la) %>% count() %>% pull(),
      subtitle = "Collisions in selected LA(s) and year(s)",
      icon = icon("map-o", lib = "font-awesome"),
      color = "blue",
      width = 4
    )
  })  # end of renderValueBox
  
  # Value box - total in your selection
  output$output_valueselection <- renderValueBox({
    shinydashboard::valueBox(
      value = dvc %>% st_drop_geometry() %>% filter(Year %in% input$input_year, Month %in% input$input_month, Accident.Description %in% input$input_la) %>% count() %>% pull(),
      subtitle = "Collisions in selection",
      icon = icon("car", lib = "font-awesome"),
      color = "blue",
      width = 4
    )
  })  # end of renderValueBox
  
  # Interactive map with Leaflet
  output$output_map <- renderLeaflet({
    dvc %>%
      filter(
        Year %in% input$input_year,
        Month %in% input$input_month,
        Accident.Description %in% input$input_la
      ) %>% 
      leaflet() %>% 
      addProviderTiles(providers$OpenStreetMap) %>% 
      addAwesomeMarkers(
        icon = awesomeIcons(
          icon = "exclamation-circle",
          iconColor = "#FFFFFF",
          library = "fa",
          markerColor = "darkblue"
        ),
        popup = ~paste0(
          "<style>
            td, th {
              text-align: left;
              padding: 3px;
            }
            </style>",
          "<table>",
          "<tr>","<td>", "Date", "</td>", "<td>", Date, "</td>", "<tr>",
          "<tr>","<td>", "LA", "</td>", "<td>", Accident.Description, "</td>", "<tr>",
          "<tr>","<td>", "City", "</td>", "<td>", City, "</td>", "<tr>",
          "<tr>","<td>", "Species", "</td>", "<td>", Severity, "</td>", "<tr>",
          "</table>"
        )
      )
  })  # end of renderLeaflet
  
  # Interactive table with DT
  output$output_table <- renderDataTable({
    dvc %>% 
      st_drop_geometry() %>%
      filter(
        Year %in% input$input_year,
        Month %in% input$input_month,
        Accident.Description %in% input$input_la
      ) %>%
      select(
       Date = Date,
        Year = Year,
        Month = Month,
        `Accident.Description` = Accident.Description,
       City = City,
        `Severity` = Severity
      ) %>%
      datatable(
        filter = "top",
        extensions = c("Scroller", "Buttons"),  # scroll instead of paginate
        rownames = FALSE,  # remove row names
        style = "bootstrap",  # style
        width = "100%",  # full width
        height = "800px",
        options = list(
          deferRender = TRUE,
          # scroll
          scrollY = 300,
          scroller = TRUE,
          # button
          autoWidth = TRUE,  # column width consistent when making selections
          dom = "Blrtip",
          buttons =
            list(
              list(
                extend = "collection",
                buttons = c("csv", "excel"),  # download extension options
                text = "Download"  # text to display
              )
            )
        )  # end of options = list()
      )  # end of datatable() 
  })  # end of renderDataTable()
  
}  # end of server function

I really appreciate your help with this issue and fixing the bug I have in my code.


Update:

Here's my data using dput():

structure(list(lat = c(40.61955, 40.61955, 40.61955, 40.61955, 
40.61955, 40.61955), long = c(-74.02346, -74.02346, -74.02346, 
-74.02346, -74.02346, -74.02346), Year = c("2020", "2020", "2019", 
"2020", "2020", "2019"), Month = c("2", "11", "10", "9", "1", 
"9"), Day = c("6", "21", "26", "20", "11", "15"), Date = c("2020-02-06", 
"2020-11-21", "2019-10-26", "2020-09-20", "2020-01-11", "2019-09-15"
), Accident.Description = c("Right lane blocked", "Two lanes blocked", 
"Two lanes blocked", "Right lane blocked", "Right lane blocked", 
"One lane blocked"), Severity = c("3", "3", "3", "3", "3", "3"
), geometry = structure(list(structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg")), structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg")), structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg")), structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg")), structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg")), structure(c(-74.02346, 40.61955), class = c("XY", 
"POINT", "sfg"))), class = c("sfc_POINT", "sfc"), precision = 0, bbox = structure(c(xmin = -74.02346, 
ymin = 40.61955, xmax = -74.02346, ymax = 40.61955), class = "bbox"), crs = structure(list(
    input = "NAD83", wkt = "GEOGCRS[\"NAD83\",\n    DATUM[\"North American Datum 1983\",\n        ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"latitude\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"longitude\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    ID[\"EPSG\",4269]]"), class = "crs"), n_empty = 0L)), row.names = c(NA, 
6L), class = c("sf", "data.frame"), sf_column = "geometry", agr = structure(c(lat = NA_integer_, 
long = NA_integer_, Year = NA_integer_, Month = NA_integer_, 
Day = NA_integer_, Date = NA_integer_, Accident.Description = NA_integer_, Severity = NA_integer_), .Label = c("constant", "aggregate", 
"identity"), class = "factor"))

Update II:

Thank you all for helping! I really appreciate all the answers you gave me!! I fixed the issues with the code but I'm still facing issues with one column which is the "accident.description" column. Although I changed the name to be "accident" where I thought the dot caused the issue but couldn't figure it out. The error message for this column below:

Error: Problem with `mutate()` column `accident.description`.
ℹ `accident.description = if_else(...)`.
x object 'accident.description' not found

This is my updated code:

dvc_wrangle <- dvc_read %>% 
  st_transform(crs = 4326) %>%  # transform coords to latlong
  # decapitalise everything for easy handling
  rename_all(tolower) %>% 
  mutate_if(is.character, tolower) %>%  # simplify strings
  # deal with dates
  mutate(
    Date = ymd(date),
    Month = case_when(
      month == 1 ~  "Jan", month == 2 ~  "Feb",
      month == 3 ~  "Mar", month == 4 ~  "Apr",
      month == 5 ~  "May", month == 6 ~  "Jun",
      month == 7 ~  "Jul", month == 8 ~  "Aug",
      month == 9 ~  "Sep", month == 10 ~ "Oct",
      month == 11 ~ "Nov", month == 12 ~ "Dec",
      TRUE ~ "Unknown"
    ),
    # clean up strings (not perfect)
    Severity = if_else(severity %in% c("1", "2", "3"), "unknown", severity),
    accident.description = if_else(accident.description == "Road closed", "Road_closed", accident.description),
    City = if_else(str_detect(city, "x") == TRUE, "unknown", city),
    City = if_else(
      city %in% c(
        "Brooklyn", "Jamaica", "Merrick", "Roosevelt", "unclassified",
      ), "unknown", city
    ),
    # final name tidy-up
    Accident.Description = str_replace_all(Accident.Description, "_", " ")
  ) %>% 
  # title case for these columns
  mutate_at(vars(Severity, Accident.Description, City), tools::toTitleCase) # To Title Case

I changed the Road closed to be "road closed" and the name of the column to be "accident" like this but still getting the same error message:

   Accident = if_else(accident %in% c("Road closed", "Two lanes blocked", "One lane blocked"), "unknown", accident),

Update III:

Thank you all for all the help and support guys! You all are amazing! I fixed the code based on your notes and regarding Update II, I changed the "Accident.Description" column name on the LHS to be in the upper case instead of small case. However, I get a new error message:

Error in rename.sf(.tbl, !!!syms) : 
  internal error: can't find `agr` columns

This is the modified code:

dvc_wrangle <- dvc_read %>% 
  st_transform(crs = 4326) %>%  # transform coords to latlong
  # decapitalise everything for easy handling
  rename_all(tolower) %>% 
  mutate_if(is.character, tolower) %>%  # simplify strings
  # deal with dates
  mutate(
    Date = ymd(date),
    Month = case_when(
      month == 1 ~  "Jan", month == 2 ~  "Feb",
      month == 3 ~  "Mar", month == 4 ~  "Apr",
      month == 5 ~  "May", month == 6 ~  "Jun",
      month == 7 ~  "Jul", month == 8 ~  "Aug",
      month == 9 ~  "Sep", month == 10 ~ "Oct",
      month == 11 ~ "Nov", month == 12 ~ "Dec",
      TRUE ~ "Unknown"
    ),
    # clean up strings (not perfect)
    Severity = if_else(severity %in% c("1", "2", "3"), "unknown", severity),
    Accident.Description = if_else(accident.description == "Road closed", "Road_closed", accident.description),
    City = if_else(str_detect(city, "x") == TRUE, "unknown", city),
    City = if_else(
      city %in% c(
        "Brooklyn", "Jamaica", "Merrick", "Roosevelt", "unclassified",
      ), "unknown", city
    ),
    # final name tidy-up
    Accident.Description = str_replace_all(accident.description, "_", " ")
  ) %>% 
  # title case for these columns
  mutate_at(vars(Severity, Accident.Description, City), tools::toTitleCase) # To Title Case

Upvotes: 2

Views: 19232

Answers (2)

Greg
Greg

Reputation: 3326

Diagnosis

Your issue is fairly simple. Once the Date column is renamed as date

  # decapitalise everything for easy handling
  rename_all(tolower) %>% 

then that problematic line

  # deal with dates
  mutate(
    Date = ymd(Date), # the issue is with line 

contains an expression ymd(Date) that refers to a nonexistent column Date.

So R searches outside the data mask for something named Date...and the first thing it finds is the function lubridate::Date(), which has (presumably) been loaded into your workspace as Date, via library(lubridate). Note that functions are also known as "closures" in R.

In that problematic expression

ymd(Date)

you are thus supplying a closure as input to ymd(), which expects a character vector. Hence the error:

x cannot coerce type 'closure' to vector of type 'character'

Solution

Simply alter your code to reference the date column, which is now lowercase.

  # deal with dates
  mutate(
    Date = ymd(date),
    #          ^^^^

Warning

As observed here by @bretauv, there are further errors later in your code. Some you can fix by making the same correction to other column names.

Upvotes: 3

bretauv
bretauv

Reputation: 8557

You put every column name to lowercase with rename_all(tolower). Therefore, column Date doesn't exist but column date does. Replacing Date by date works.

You have to fix that for all other column names in mutate(). Also, you modify the variable City but it is not in the data you provide (perhaps you just forgot to include it).

I didn't run the app but this should fix your dplyr error.

Upvotes: 2

Related Questions