Contexto

La base de datos USArrests contiene estadísticas en arrestos por cada 100,000 residentes por agresión, asesinato y violación en cada uno de los 50 estados de E.E.U.U. en 1973.

Instalar paquetes y llamar librerias

#install.packages("caret") # Algoritmos de aprendizaje automático
library(caret)
#install.packages("datasets") # Para usar la base de datos "USArrests"
library(datasets)
#install.packages("ggplot2") # Gráficas con mejor diseño
library(ggplot2)
#install.packages("lattice") # Crear gráficos
library(lattice)
#install.packages("DataExplorer") # Análisis Descriptivo
library(DataExplorer)
#install.packages("kernlab") # Modelos de SVM
library(kernlab)
#install.packages("dplyr") # Manipulación de datos
library(dplyr)
library(cluster)
library(factoextra)
library(data.table)
library(tidyverse)
#install.packages("tigris")
library(tigris)
library(randomForest)
library(sf)
library(shiny)

Importar las bases de datos

datos <- USArrests
datos_escalados <- scale(datos)

Configurar tigris para descargar el mapa de EE.UU.

options(tigris_use_cache = TRUE)
us_map <- tigris::states(cb = TRUE)
## Retrieving data for the year 2021

Entrenar modelo Random Forest

set.seed(123)
segmentos <- kmeans(datos_escalados, centers = 4, nstart = 25)
asignacion <- cbind(datos, cluster = segmentos$cluster)

Normalizar Nombres de los Estados

asignacion$state <- tolower(rownames(asignacion))
us_map$NAME <- tolower(us_map$NAME)

Asignar niveles de Seguridad

asignacion$nivel_seguridad <- factor(case_when(
  asignacion$cluster == 1 ~ "Bajo",
  asignacion$cluster == 2 ~ "Medio",
  asignacion$cluster == 3 ~ "Alto",
  asignacion$cluster == 4 ~ "Muy Alto",
  TRUE ~ "Desconocido"
))

Entrenar el modelo Random Forest

modelo_rf <- randomForest(
  nivel_seguridad ~ Murder + Assault + Rape + UrbanPop, 
  data = asignacion,
  ntree = 100
)

Interfaz de Usuario (UI)

ui <- fluidPage(
  titlePanel("Predicción de Seguridad en EE.UU."),
  
  sidebarLayout(
    sidebarPanel(
      h4("Ingrese sus datos para predicción"),
      numericInput("murder", "Asesinatos por 100,000 hab.:", value = 10, min = 0),
      numericInput("assault", "Agresiones por 100,000 hab.:", value = 200, min = 0),
      numericInput("rape", "Violaciones por 100,000 hab.:", value = 20, min = 0),
      numericInput("urbanpop", "Porcentaje de población urbana:", value = 50, min = 0, max = 100),
      actionButton("predict", "Predecir Seguridad"),
      hr(),
      h4("Predicción del nivel de seguridad"),
      verbatimTextOutput("prediction_output")
    ),
    
    mainPanel(
      tabsetPanel(
        tabPanel("Mapa de Seguridad",
                 plotOutput("mapaPlot")
        ),
        tabPanel("Estados Más y Menos Seguros",
                 tableOutput("top5_safe"),
                 tableOutput("top5_unsafe")
        )
      )
    )
  )
)

# Servidor (Server)
server <- function(input, output, session) {
  
  # Predecir el nivel de seguridad basado en la entrada del usuario
  observeEvent(input$predict, {
    new_data <- data.frame(
      Murder = input$murder,
      Assault = input$assault,
      Rape = input$rape,
      UrbanPop = input$urbanpop
    )
    
    prediccion <- predict(modelo_rf, new_data)
    output$prediction_output <- renderPrint({ paste("Nivel de Seguridad:", prediccion) })
  })
  
  # Graficar el mapa con los clusters de seguridad
  output$mapaPlot <- renderPlot({
    us_clustered <- left_join(us_map, asignacion, by = c("NAME" = "state"))
    
    colores_seguridad <- c("Bajo" = "darkgreen", 
                           "Medio" = "yellow", 
                           "Alto" = "orange", 
                           "Muy Alto" = "red")
    
    ggplot(data = us_clustered) +
      geom_sf(aes(fill = nivel_seguridad), color = "black", size = 0.3) +
      scale_fill_manual(values = colores_seguridad, name = "Nivel de Seguridad") +
      labs(title = "Mapa de Seguridad en EE.UU. (1973)",
           subtitle = "Clasificación basada en tasas de criminalidad",
           caption = "Fuente: USArrests") +
      theme_minimal()
  })
  
  
  output$top5_safe <- renderTable({
    asignacion %>%
      arrange(Murder + Assault + Rape) %>%
      head(5) %>%
      select(state, Murder, Assault, Rape, nivel_seguridad)
  }, caption = "🟢 Estados Más Seguros")
  
  output$top5_unsafe <- renderTable({
    asignacion %>%
      arrange(desc(Murder + Assault + Rape)) %>%
      head(5) %>%
      select(state, Murder, Assault, Rape, nivel_seguridad)
  }, caption = "🔴 Estados Más Inseguros")
}

shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents
LS0tCnRpdGxlOiAiVVNBcnJlc3QiCmF1dGhvcjogIkEwMTczNDI5OV9GcmFuY2lzY28gU2FuZG92YWwgSGlkYWxnbyIKZGF0ZTogIjIwMjUtMDItMjEiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFCiAgICB0aGVtZTogam91cm5hbAotLS0KCiFbXSgvVXNlcnMvcm9uaWUvRGVza3RvcC9DbGFzZXMgVGVjL0NvbmNlbnRyYWNpb8yBbi9wdXJnYS5naWYpCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+Q29udGV4dG88L3NwYW4+CkxhIGJhc2UgZGUgZGF0b3MgKlVTQXJyZXN0cyogY29udGllbmUgZXN0YWTDrXN0aWNhcyBlbiBhcnJlc3RvcyBwb3IgY2FkYSAxMDAsMDAwIHJlc2lkZW50ZXMgcG9yIGFncmVzacOzbiwgYXNlc2luYXRvIHkgdmlvbGFjacOzbiBlbiBjYWRhIHVubyBkZSBsb3MgNTAgZXN0YWRvcyBkZSBFLkUuVS5VLiBlbiAxOTczLgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcmlhczwvc3Bhbj4KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KCiNpbnN0YWxsLnBhY2thZ2VzKCJjYXJldCIpICMgQWxnb3JpdG1vcyBkZSBhcHJlbmRpemFqZSBhdXRvbcOhdGljbwpsaWJyYXJ5KGNhcmV0KQojaW5zdGFsbC5wYWNrYWdlcygiZGF0YXNldHMiKSAjIFBhcmEgdXNhciBsYSBiYXNlIGRlIGRhdG9zICJVU0FycmVzdHMiCmxpYnJhcnkoZGF0YXNldHMpCiNpbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikgIyBHcsOhZmljYXMgY29uIG1lam9yIGRpc2XDsW8KbGlicmFyeShnZ3Bsb3QyKQojaW5zdGFsbC5wYWNrYWdlcygibGF0dGljZSIpICMgQ3JlYXIgZ3LDoWZpY29zCmxpYnJhcnkobGF0dGljZSkKI2luc3RhbGwucGFja2FnZXMoIkRhdGFFeHBsb3JlciIpICMgQW7DoWxpc2lzIERlc2NyaXB0aXZvCmxpYnJhcnkoRGF0YUV4cGxvcmVyKQojaW5zdGFsbC5wYWNrYWdlcygia2VybmxhYiIpICMgTW9kZWxvcyBkZSBTVk0KbGlicmFyeShrZXJubGFiKQojaW5zdGFsbC5wYWNrYWdlcygiZHBseXIiKSAjIE1hbmlwdWxhY2nDs24gZGUgZGF0b3MKbGlicmFyeShkcGx5cikKbGlicmFyeShjbHVzdGVyKQpsaWJyYXJ5KGZhY3RvZXh0cmEpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeSh0aWR5dmVyc2UpCiNpbnN0YWxsLnBhY2thZ2VzKCJ0aWdyaXMiKQpsaWJyYXJ5KHRpZ3JpcykKbGlicmFyeShyYW5kb21Gb3Jlc3QpCmxpYnJhcnkoc2YpCmxpYnJhcnkoc2hpbnkpCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5JbXBvcnRhciBsYXMgYmFzZXMgZGUgZGF0b3M8L3NwYW4+CmBgYHtyfQoKZGF0b3MgPC0gVVNBcnJlc3RzCmRhdG9zX2VzY2FsYWRvcyA8LSBzY2FsZShkYXRvcykKCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPkNvbmZpZ3VyYXIgdGlncmlzIHBhcmEgZGVzY2FyZ2FyIGVsIG1hcGEgZGUgRUUuVVUuPC9zcGFuPgpgYGB7cn0KCm9wdGlvbnModGlncmlzX3VzZV9jYWNoZSA9IFRSVUUpCnVzX21hcCA8LSB0aWdyaXM6OnN0YXRlcyhjYiA9IFRSVUUpCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5FbnRyZW5hciBtb2RlbG8gUmFuZG9tIEZvcmVzdDwvc3Bhbj4KYGBge3J9CgpzZXQuc2VlZCgxMjMpCnNlZ21lbnRvcyA8LSBrbWVhbnMoZGF0b3NfZXNjYWxhZG9zLCBjZW50ZXJzID0gNCwgbnN0YXJ0ID0gMjUpCmFzaWduYWNpb24gPC0gY2JpbmQoZGF0b3MsIGNsdXN0ZXIgPSBzZWdtZW50b3MkY2x1c3RlcikKCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IHJlZDsiPk5vcm1hbGl6YXIgTm9tYnJlcyBkZSBsb3MgRXN0YWRvczwvc3Bhbj4KYGBge3J9Cgphc2lnbmFjaW9uJHN0YXRlIDwtIHRvbG93ZXIocm93bmFtZXMoYXNpZ25hY2lvbikpCnVzX21hcCROQU1FIDwtIHRvbG93ZXIodXNfbWFwJE5BTUUpCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5Bc2lnbmFyIG5pdmVsZXMgZGUgU2VndXJpZGFkPC9zcGFuPgpgYGB7cn0KCmFzaWduYWNpb24kbml2ZWxfc2VndXJpZGFkIDwtIGZhY3RvcihjYXNlX3doZW4oCiAgYXNpZ25hY2lvbiRjbHVzdGVyID09IDEgfiAiQmFqbyIsCiAgYXNpZ25hY2lvbiRjbHVzdGVyID09IDIgfiAiTWVkaW8iLAogIGFzaWduYWNpb24kY2x1c3RlciA9PSAzIH4gIkFsdG8iLAogIGFzaWduYWNpb24kY2x1c3RlciA9PSA0IH4gIk11eSBBbHRvIiwKICBUUlVFIH4gIkRlc2Nvbm9jaWRvIgopKQoKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogcmVkOyI+RW50cmVuYXIgZWwgbW9kZWxvIFJhbmRvbSBGb3Jlc3Q8L3NwYW4+CmBgYHtyfQoKbW9kZWxvX3JmIDwtIHJhbmRvbUZvcmVzdCgKICBuaXZlbF9zZWd1cmlkYWQgfiBNdXJkZXIgKyBBc3NhdWx0ICsgUmFwZSArIFVyYmFuUG9wLCAKICBkYXRhID0gYXNpZ25hY2lvbiwKICBudHJlZSA9IDEwMAopCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiByZWQ7Ij5JbnRlcmZheiBkZSBVc3VhcmlvIChVSSk8L3NwYW4+CmBgYHtyfQoKdWkgPC0gZmx1aWRQYWdlKAogIHRpdGxlUGFuZWwoIlByZWRpY2Npw7NuIGRlIFNlZ3VyaWRhZCBlbiBFRS5VVS4iKSwKICAKICBzaWRlYmFyTGF5b3V0KAogICAgc2lkZWJhclBhbmVsKAogICAgICBoNCgiSW5ncmVzZSBzdXMgZGF0b3MgcGFyYSBwcmVkaWNjacOzbiIpLAogICAgICBudW1lcmljSW5wdXQoIm11cmRlciIsICJBc2VzaW5hdG9zIHBvciAxMDAsMDAwIGhhYi46IiwgdmFsdWUgPSAxMCwgbWluID0gMCksCiAgICAgIG51bWVyaWNJbnB1dCgiYXNzYXVsdCIsICJBZ3Jlc2lvbmVzIHBvciAxMDAsMDAwIGhhYi46IiwgdmFsdWUgPSAyMDAsIG1pbiA9IDApLAogICAgICBudW1lcmljSW5wdXQoInJhcGUiLCAiVmlvbGFjaW9uZXMgcG9yIDEwMCwwMDAgaGFiLjoiLCB2YWx1ZSA9IDIwLCBtaW4gPSAwKSwKICAgICAgbnVtZXJpY0lucHV0KCJ1cmJhbnBvcCIsICJQb3JjZW50YWplIGRlIHBvYmxhY2nDs24gdXJiYW5hOiIsIHZhbHVlID0gNTAsIG1pbiA9IDAsIG1heCA9IDEwMCksCiAgICAgIGFjdGlvbkJ1dHRvbigicHJlZGljdCIsICJQcmVkZWNpciBTZWd1cmlkYWQiKSwKICAgICAgaHIoKSwKICAgICAgaDQoIlByZWRpY2Npw7NuIGRlbCBuaXZlbCBkZSBzZWd1cmlkYWQiKSwKICAgICAgdmVyYmF0aW1UZXh0T3V0cHV0KCJwcmVkaWN0aW9uX291dHB1dCIpCiAgICApLAogICAgCiAgICBtYWluUGFuZWwoCiAgICAgIHRhYnNldFBhbmVsKAogICAgICAgIHRhYlBhbmVsKCJNYXBhIGRlIFNlZ3VyaWRhZCIsCiAgICAgICAgICAgICAgICAgcGxvdE91dHB1dCgibWFwYVBsb3QiKQogICAgICAgICksCiAgICAgICAgdGFiUGFuZWwoIkVzdGFkb3MgTcOhcyB5IE1lbm9zIFNlZ3Vyb3MiLAogICAgICAgICAgICAgICAgIHRhYmxlT3V0cHV0KCJ0b3A1X3NhZmUiKSwKICAgICAgICAgICAgICAgICB0YWJsZU91dHB1dCgidG9wNV91bnNhZmUiKQogICAgICAgICkKICAgICAgKQogICAgKQogICkKKQoKIyBTZXJ2aWRvciAoU2VydmVyKQpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCwgc2Vzc2lvbikgewogIAogICMgUHJlZGVjaXIgZWwgbml2ZWwgZGUgc2VndXJpZGFkIGJhc2FkbyBlbiBsYSBlbnRyYWRhIGRlbCB1c3VhcmlvCiAgb2JzZXJ2ZUV2ZW50KGlucHV0JHByZWRpY3QsIHsKICAgIG5ld19kYXRhIDwtIGRhdGEuZnJhbWUoCiAgICAgIE11cmRlciA9IGlucHV0JG11cmRlciwKICAgICAgQXNzYXVsdCA9IGlucHV0JGFzc2F1bHQsCiAgICAgIFJhcGUgPSBpbnB1dCRyYXBlLAogICAgICBVcmJhblBvcCA9IGlucHV0JHVyYmFucG9wCiAgICApCiAgICAKICAgIHByZWRpY2Npb24gPC0gcHJlZGljdChtb2RlbG9fcmYsIG5ld19kYXRhKQogICAgb3V0cHV0JHByZWRpY3Rpb25fb3V0cHV0IDwtIHJlbmRlclByaW50KHsgcGFzdGUoIk5pdmVsIGRlIFNlZ3VyaWRhZDoiLCBwcmVkaWNjaW9uKSB9KQogIH0pCiAgCiAgIyBHcmFmaWNhciBlbCBtYXBhIGNvbiBsb3MgY2x1c3RlcnMgZGUgc2VndXJpZGFkCiAgb3V0cHV0JG1hcGFQbG90IDwtIHJlbmRlclBsb3QoewogICAgdXNfY2x1c3RlcmVkIDwtIGxlZnRfam9pbih1c19tYXAsIGFzaWduYWNpb24sIGJ5ID0gYygiTkFNRSIgPSAic3RhdGUiKSkKICAgIAogICAgY29sb3Jlc19zZWd1cmlkYWQgPC0gYygiQmFqbyIgPSAiZGFya2dyZWVuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpbyIgPSAieWVsbG93IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJBbHRvIiA9ICJvcmFuZ2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIk11eSBBbHRvIiA9ICJyZWQiKQogICAgCiAgICBnZ3Bsb3QoZGF0YSA9IHVzX2NsdXN0ZXJlZCkgKwogICAgICBnZW9tX3NmKGFlcyhmaWxsID0gbml2ZWxfc2VndXJpZGFkKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMC4zKSArCiAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNvbG9yZXNfc2VndXJpZGFkLCBuYW1lID0gIk5pdmVsIGRlIFNlZ3VyaWRhZCIpICsKICAgICAgbGFicyh0aXRsZSA9ICJNYXBhIGRlIFNlZ3VyaWRhZCBlbiBFRS5VVS4gKDE5NzMpIiwKICAgICAgICAgICBzdWJ0aXRsZSA9ICJDbGFzaWZpY2FjacOzbiBiYXNhZGEgZW4gdGFzYXMgZGUgY3JpbWluYWxpZGFkIiwKICAgICAgICAgICBjYXB0aW9uID0gIkZ1ZW50ZTogVVNBcnJlc3RzIikgKwogICAgICB0aGVtZV9taW5pbWFsKCkKICB9KQogIAogIAogIG91dHB1dCR0b3A1X3NhZmUgPC0gcmVuZGVyVGFibGUoewogICAgYXNpZ25hY2lvbiAlPiUKICAgICAgYXJyYW5nZShNdXJkZXIgKyBBc3NhdWx0ICsgUmFwZSkgJT4lCiAgICAgIGhlYWQoNSkgJT4lCiAgICAgIHNlbGVjdChzdGF0ZSwgTXVyZGVyLCBBc3NhdWx0LCBSYXBlLCBuaXZlbF9zZWd1cmlkYWQpCiAgfSwgY2FwdGlvbiA9ICLwn5+iIEVzdGFkb3MgTcOhcyBTZWd1cm9zIikKICAKICBvdXRwdXQkdG9wNV91bnNhZmUgPC0gcmVuZGVyVGFibGUoewogICAgYXNpZ25hY2lvbiAlPiUKICAgICAgYXJyYW5nZShkZXNjKE11cmRlciArIEFzc2F1bHQgKyBSYXBlKSkgJT4lCiAgICAgIGhlYWQoNSkgJT4lCiAgICAgIHNlbGVjdChzdGF0ZSwgTXVyZGVyLCBBc3NhdWx0LCBSYXBlLCBuaXZlbF9zZWd1cmlkYWQpCiAgfSwgY2FwdGlvbiA9ICLwn5S0IEVzdGFkb3MgTcOhcyBJbnNlZ3Vyb3MiKQp9CgpzaGlueUFwcCh1aSA9IHVpLCBzZXJ2ZXIgPSBzZXJ2ZXIpCgpgYGAK