Instalar paquetes y llamar
librerías
library(shiny)
library(randomForest)
## randomForest 4.7-1.2
## Type rfNews() to see new features/changes/bug fixes.
library(ggplot2)
##
## Attaching package: 'ggplot2'
## The following object is masked from 'package:randomForest':
##
## margin
library(rsconnect) # Para desplegar en shinyapps.io
##
## Attaching package: 'rsconnect'
## The following object is masked from 'package:shiny':
##
## serverInfo
Simulación de datos para entrenar el
modelo (puedes reemplazar con tu dataset real)
set.seed(123)
n <- 1000
df <- data.frame(
Tenure = runif(n, min = 1, max = 60), # Tiempo de suscripción (meses)
MonthlyCharges = runif(n, min = 10, max = 100), # Cargos mensuales
TotalCharges = runif(n, min = 100, max = 5000), # Cargos totales
Contract = sample(c("Month-to-month", "One year", "Two year"), n, replace = TRUE),
Churn = sample(c(0, 1), n, replace = TRUE, prob = c(0.8, 0.2)) # Churn = 1 (Abandona)
)
Convertir variables categóricas a
factores
df$Contract <- as.factor(df$Contract)
df$Churn <- as.factor(df$Churn)
Dividir en entrenamiento y
prueba
set.seed(123)
train_index <- sample(1:nrow(df), 0.7 * nrow(df))
train_data <- df[train_index, ]
test_data <- df[-train_index, ]
Entrenar el modelo Random
Forest
modelo_rf <- randomForest(Churn ~ ., data = train_data, ntree = 500, importance = TRUE)
Interfaz de Usuario (UI)
ui <- fluidPage(
titlePanel("Predicción de Churn"),
sidebarLayout(
sidebarPanel(
h4("Ingrese los valores del cliente"),
numericInput("tenure", "Tiempo de suscripción (meses):", value = 12, min = 1, max = 60),
numericInput("monthly_charges", "Cargos mensuales ($):", value = 50, min = 10, max = 100),
numericInput("total_charges", "Cargos totales ($):", value = 600, min = 100, max = 5000),
selectInput("contract", "Tipo de Contrato:",
choices = c("Month-to-month", "One year", "Two year"),
selected = "Month-to-month"),
actionButton("predict", "Predecir Churn"),
hr(),
h4("Predicción"),
verbatimTextOutput("prediction_output"),
verbatimTextOutput("prob_output")
),
mainPanel(
tabsetPanel(
tabPanel("Probabilidad de Churn",
plotOutput("churnPlot")
),
tabPanel("Importancia de Variables",
plotOutput("importancePlot")
)
)
)
)
)
# Servidor (Server)
server <- function(input, output, session) {
# Predecir la probabilidad de churn basado en la entrada del usuario
observeEvent(input$predict, {
new_data <- data.frame(
Tenure = input$tenure,
MonthlyCharges = input$monthly_charges,
TotalCharges = input$total_charges,
Contract = factor(input$contract, levels = levels(train_data$Contract))
)
prediccion <- predict(modelo_rf, new_data, type = "prob")
clase_predicha <- predict(modelo_rf, new_data)
output$prediction_output <- renderPrint({ paste("Predicción de Churn:", clase_predicha) })
output$prob_output <- renderPrint({ paste("Probabilidad de Churn:", round(prediccion[1,2] * 100, 2), "%") })
})
# Graficar la probabilidad de churn vs. no churn
output$churnPlot <- renderPlot({
req(input$predict) # Esperar a que el usuario haga una predicción
prediccion <- predict(modelo_rf, data.frame(
Tenure = input$tenure,
MonthlyCharges = input$monthly_charges,
TotalCharges = input$total_charges,
Contract = factor(input$contract, levels = levels(train_data$Contract))
), type = "prob")
datos_prob <- data.frame(
Clase = c("No Churn", "Churn"),
Probabilidad = c(prediccion[1,1], prediccion[1,2])
)
ggplot(datos_prob, aes(x = Clase, y = Probabilidad, fill = Clase)) +
geom_bar(stat = "identity", color = "black") +
scale_fill_manual(values = c("No Churn" = "green", "Churn" = "red")) +
labs(title = "Probabilidad de Churn vs No Churn",
y = "Probabilidad",
x = "Clase") +
theme_minimal()
})
# Graficar importancia de variables en el modelo
output$importancePlot <- renderPlot({
varImpPlot(modelo_rf)
})
}
# Verificar que server y ui están correctamente definidos
print(exists("server")) # Debería imprimir TRUE
## [1] TRUE
print(exists("ui")) # Debería imprimir TRUE
## [1] TRUE
Ejecutar la aplicación
shinyApp(ui = ui, server = server)
Shiny applications not supported in static R Markdown documents
LS0tCnRpdGxlOiAiQ0hVUk4iCmF1dGhvcjogIkEwMTczNDI5OV9GcmFuY2lzY28gU2FuZG92YWwgSGlkYWxnbyIKZGF0ZTogIjIwMjUtMDMtMDIiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFCiAgICB0aGVtZTogam91cm5hbAotLS0KCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+SW5zdGFsYXIgcGFxdWV0ZXMgeSBsbGFtYXIgbGlicmVyw61hczwvc3Bhbj4KYGBge3J9CgpsaWJyYXJ5KHNoaW55KQpsaWJyYXJ5KHJhbmRvbUZvcmVzdCkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJzY29ubmVjdCkgICMgUGFyYSBkZXNwbGVnYXIgZW4gc2hpbnlhcHBzLmlvCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+U2ltdWxhY2nDs24gZGUgZGF0b3MgcGFyYSBlbnRyZW5hciBlbCBtb2RlbG8gKHB1ZWRlcyByZWVtcGxhemFyIGNvbiB0dSBkYXRhc2V0IHJlYWwpPC9zcGFuPgpgYGB7cn0KCnNldC5zZWVkKDEyMykKbiA8LSAxMDAwCmRmIDwtIGRhdGEuZnJhbWUoCiAgVGVudXJlID0gcnVuaWYobiwgbWluID0gMSwgbWF4ID0gNjApLCAgIyBUaWVtcG8gZGUgc3VzY3JpcGNpw7NuIChtZXNlcykKICBNb250aGx5Q2hhcmdlcyA9IHJ1bmlmKG4sIG1pbiA9IDEwLCBtYXggPSAxMDApLCAgIyBDYXJnb3MgbWVuc3VhbGVzCiAgVG90YWxDaGFyZ2VzID0gcnVuaWYobiwgbWluID0gMTAwLCBtYXggPSA1MDAwKSwgICMgQ2FyZ29zIHRvdGFsZXMKICBDb250cmFjdCA9IHNhbXBsZShjKCJNb250aC10by1tb250aCIsICJPbmUgeWVhciIsICJUd28geWVhciIpLCBuLCByZXBsYWNlID0gVFJVRSksCiAgQ2h1cm4gPSBzYW1wbGUoYygwLCAxKSwgbiwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuOCwgMC4yKSkgICMgQ2h1cm4gPSAxIChBYmFuZG9uYSkKKQoKYGBgCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkNvbnZlcnRpciB2YXJpYWJsZXMgY2F0ZWfDs3JpY2FzIGEgZmFjdG9yZXM8L3NwYW4+CmBgYHtyfQoKZGYkQ29udHJhY3QgPC0gYXMuZmFjdG9yKGRmJENvbnRyYWN0KQpkZiRDaHVybiA8LSBhcy5mYWN0b3IoZGYkQ2h1cm4pCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RGl2aWRpciBlbiBlbnRyZW5hbWllbnRvIHkgcHJ1ZWJhPC9zcGFuPgpgYGB7cn0KCnNldC5zZWVkKDEyMykKdHJhaW5faW5kZXggPC0gc2FtcGxlKDE6bnJvdyhkZiksIDAuNyAqIG5yb3coZGYpKQp0cmFpbl9kYXRhIDwtIGRmW3RyYWluX2luZGV4LCBdCnRlc3RfZGF0YSA8LSBkZlstdHJhaW5faW5kZXgsIF0KCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5FbnRyZW5hciBlbCBtb2RlbG8gUmFuZG9tIEZvcmVzdDwvc3Bhbj4KYGBge3J9Cgptb2RlbG9fcmYgPC0gcmFuZG9tRm9yZXN0KENodXJuIH4gLiwgZGF0YSA9IHRyYWluX2RhdGEsIG50cmVlID0gNTAwLCBpbXBvcnRhbmNlID0gVFJVRSkKCmBgYAoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5JbnRlcmZheiBkZSBVc3VhcmlvIChVSSk8L3NwYW4+CmBgYHtyfQoKdWkgPC0gZmx1aWRQYWdlKAogIHRpdGxlUGFuZWwoIlByZWRpY2Npw7NuIGRlIENodXJuIiksCiAgCiAgc2lkZWJhckxheW91dCgKICAgIHNpZGViYXJQYW5lbCgKICAgICAgaDQoIkluZ3Jlc2UgbG9zIHZhbG9yZXMgZGVsIGNsaWVudGUiKSwKICAgICAgbnVtZXJpY0lucHV0KCJ0ZW51cmUiLCAiVGllbXBvIGRlIHN1c2NyaXBjacOzbiAobWVzZXMpOiIsIHZhbHVlID0gMTIsIG1pbiA9IDEsIG1heCA9IDYwKSwKICAgICAgbnVtZXJpY0lucHV0KCJtb250aGx5X2NoYXJnZXMiLCAiQ2FyZ29zIG1lbnN1YWxlcyAoJCk6IiwgdmFsdWUgPSA1MCwgbWluID0gMTAsIG1heCA9IDEwMCksCiAgICAgIG51bWVyaWNJbnB1dCgidG90YWxfY2hhcmdlcyIsICJDYXJnb3MgdG90YWxlcyAoJCk6IiwgdmFsdWUgPSA2MDAsIG1pbiA9IDEwMCwgbWF4ID0gNTAwMCksCiAgICAgIHNlbGVjdElucHV0KCJjb250cmFjdCIsICJUaXBvIGRlIENvbnRyYXRvOiIsCiAgICAgICAgICAgICAgICAgIGNob2ljZXMgPSBjKCJNb250aC10by1tb250aCIsICJPbmUgeWVhciIsICJUd28geWVhciIpLAogICAgICAgICAgICAgICAgICBzZWxlY3RlZCA9ICJNb250aC10by1tb250aCIpLAogICAgICBhY3Rpb25CdXR0b24oInByZWRpY3QiLCAiUHJlZGVjaXIgQ2h1cm4iKSwKICAgICAgaHIoKSwKICAgICAgaDQoIlByZWRpY2Npw7NuIiksCiAgICAgIHZlcmJhdGltVGV4dE91dHB1dCgicHJlZGljdGlvbl9vdXRwdXQiKSwKICAgICAgdmVyYmF0aW1UZXh0T3V0cHV0KCJwcm9iX291dHB1dCIpCiAgICApLAogICAgCiAgICBtYWluUGFuZWwoCiAgICAgIHRhYnNldFBhbmVsKAogICAgICAgIHRhYlBhbmVsKCJQcm9iYWJpbGlkYWQgZGUgQ2h1cm4iLAogICAgICAgICAgICAgICAgIHBsb3RPdXRwdXQoImNodXJuUGxvdCIpCiAgICAgICAgKSwKICAgICAgICB0YWJQYW5lbCgiSW1wb3J0YW5jaWEgZGUgVmFyaWFibGVzIiwKICAgICAgICAgICAgICAgICBwbG90T3V0cHV0KCJpbXBvcnRhbmNlUGxvdCIpCiAgICAgICAgKQogICAgICApCiAgICApCiAgKQopCgpgYGAKCmBgYHtyfQoKIyBTZXJ2aWRvciAoU2VydmVyKQpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCwgc2Vzc2lvbikgewogIAogICMgUHJlZGVjaXIgbGEgcHJvYmFiaWxpZGFkIGRlIGNodXJuIGJhc2FkbyBlbiBsYSBlbnRyYWRhIGRlbCB1c3VhcmlvCiAgb2JzZXJ2ZUV2ZW50KGlucHV0JHByZWRpY3QsIHsKICAgIG5ld19kYXRhIDwtIGRhdGEuZnJhbWUoCiAgICAgIFRlbnVyZSA9IGlucHV0JHRlbnVyZSwKICAgICAgTW9udGhseUNoYXJnZXMgPSBpbnB1dCRtb250aGx5X2NoYXJnZXMsCiAgICAgIFRvdGFsQ2hhcmdlcyA9IGlucHV0JHRvdGFsX2NoYXJnZXMsCiAgICAgIENvbnRyYWN0ID0gZmFjdG9yKGlucHV0JGNvbnRyYWN0LCBsZXZlbHMgPSBsZXZlbHModHJhaW5fZGF0YSRDb250cmFjdCkpCiAgICApCiAgICAKICAgIHByZWRpY2Npb24gPC0gcHJlZGljdChtb2RlbG9fcmYsIG5ld19kYXRhLCB0eXBlID0gInByb2IiKQogICAgY2xhc2VfcHJlZGljaGEgPC0gcHJlZGljdChtb2RlbG9fcmYsIG5ld19kYXRhKQogICAgCiAgICBvdXRwdXQkcHJlZGljdGlvbl9vdXRwdXQgPC0gcmVuZGVyUHJpbnQoeyBwYXN0ZSgiUHJlZGljY2nDs24gZGUgQ2h1cm46IiwgY2xhc2VfcHJlZGljaGEpIH0pCiAgICBvdXRwdXQkcHJvYl9vdXRwdXQgPC0gcmVuZGVyUHJpbnQoeyBwYXN0ZSgiUHJvYmFiaWxpZGFkIGRlIENodXJuOiIsIHJvdW5kKHByZWRpY2Npb25bMSwyXSAqIDEwMCwgMiksICIlIikgfSkKICB9KQogIAogICMgR3JhZmljYXIgbGEgcHJvYmFiaWxpZGFkIGRlIGNodXJuIHZzLiBubyBjaHVybgogIG91dHB1dCRjaHVyblBsb3QgPC0gcmVuZGVyUGxvdCh7CiAgICByZXEoaW5wdXQkcHJlZGljdCkgICMgRXNwZXJhciBhIHF1ZSBlbCB1c3VhcmlvIGhhZ2EgdW5hIHByZWRpY2Npw7NuCiAgICBwcmVkaWNjaW9uIDwtIHByZWRpY3QobW9kZWxvX3JmLCBkYXRhLmZyYW1lKAogICAgICBUZW51cmUgPSBpbnB1dCR0ZW51cmUsCiAgICAgIE1vbnRobHlDaGFyZ2VzID0gaW5wdXQkbW9udGhseV9jaGFyZ2VzLAogICAgICBUb3RhbENoYXJnZXMgPSBpbnB1dCR0b3RhbF9jaGFyZ2VzLAogICAgICBDb250cmFjdCA9IGZhY3RvcihpbnB1dCRjb250cmFjdCwgbGV2ZWxzID0gbGV2ZWxzKHRyYWluX2RhdGEkQ29udHJhY3QpKQogICAgKSwgdHlwZSA9ICJwcm9iIikKICAgIAogICAgZGF0b3NfcHJvYiA8LSBkYXRhLmZyYW1lKAogICAgICBDbGFzZSA9IGMoIk5vIENodXJuIiwgIkNodXJuIiksCiAgICAgIFByb2JhYmlsaWRhZCA9IGMocHJlZGljY2lvblsxLDFdLCBwcmVkaWNjaW9uWzEsMl0pCiAgICApCiAgICAKICAgIGdncGxvdChkYXRvc19wcm9iLCBhZXMoeCA9IENsYXNlLCB5ID0gUHJvYmFiaWxpZGFkLCBmaWxsID0gQ2xhc2UpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBjb2xvciA9ICJibGFjayIpICsKICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiTm8gQ2h1cm4iID0gImdyZWVuIiwgIkNodXJuIiA9ICJyZWQiKSkgKwogICAgICBsYWJzKHRpdGxlID0gIlByb2JhYmlsaWRhZCBkZSBDaHVybiB2cyBObyBDaHVybiIsCiAgICAgICAgICAgeSA9ICJQcm9iYWJpbGlkYWQiLAogICAgICAgICAgIHggPSAiQ2xhc2UiKSArCiAgICAgIHRoZW1lX21pbmltYWwoKQogIH0pCiAgCiAgIyBHcmFmaWNhciBpbXBvcnRhbmNpYSBkZSB2YXJpYWJsZXMgZW4gZWwgbW9kZWxvCiAgb3V0cHV0JGltcG9ydGFuY2VQbG90IDwtIHJlbmRlclBsb3QoewogICAgdmFySW1wUGxvdChtb2RlbG9fcmYpCiAgfSkKfQoKIyBWZXJpZmljYXIgcXVlIHNlcnZlciB5IHVpIGVzdMOhbiBjb3JyZWN0YW1lbnRlIGRlZmluaWRvcwpwcmludChleGlzdHMoInNlcnZlciIpKSAgIyBEZWJlcsOtYSBpbXByaW1pciBUUlVFCnByaW50KGV4aXN0cygidWkiKSkgICAgICAjIERlYmVyw61hIGltcHJpbWlyIFRSVUUKCgpgYGAKCiMgPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RWplY3V0YXIgbGEgYXBsaWNhY2nDs248L3NwYW4+CmBgYHtyfQoKc2hpbnlBcHAodWkgPSB1aSwgc2VydmVyID0gc2VydmVyKQoKYGBgCgoK