Escenario:
Cyclistic: Un programa de bicicletas compartidas que incluye 5,800 bicicletas y 600 estaciones. Cyclistic se destaca por ofrecer también bicicletas reclinadas, triciclos manuales y bicicletas de carga que ofrecen un uso más inclusivo de las bicicletas compartidas para las personas con discapacidad y los ciclistas que no pueden utilizar una bicicleta estándar de dos ruedas. La mayoría de los ciclistas eligen las bicicletas tradicionales, alrededor de un 8% de los ciclistas usan las opciones asistidas. Los usuarios de Cyclistic son más propensos a utilizar la bicicleta para recreación, pero alrededor del 30% la utiliza para ir al trabajo cada día.
Objetivo del Análisis:
Comprender los patrones de uso de bicicletas compartidas.
Identificar diferencias entre usuario casual y miembro.
Encontrar oportunidades para mejorar el servicio.
1- Importación y Preparación de Datos
Importar los archivos CSV.
enero <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202401-divvy-tripdata.csv")
febrero <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202402-divvy-tripdata.csv")
marzo <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202403-divvy-tripdata.csv")
abril <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202404-divvy-tripdata.csv")
mayo <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202405-divvy-tripdata.csv")
junio <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202406-divvy-tripdata.csv")
julio <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202407-divvy-tripdata.csv")
agosto <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202408-divvy-tripdata.csv")
septiembre <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202409-divvy-tripdata.csv")
octubre <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202410-divvy-tripdata.csv")
noviembre <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202411-divvy-tripdata.csv")
diciembre <- read_csv("C:/Users/bruji/OneDrive/Desktop/Caso Data Analyst/202412-divvy-tripdata.csv")
Comprobamos los nombres de las columnas de los archivos importados para ver si hay diferencias.
> colnames(enero) .... (de Enero a Diciembre)
[1] "ride_id" "rideable_type" "started_at" "ended_at" "start_station_name"
[6] "start_station_id" "end_station_name" "end_station_id" "start_lat" "start_lng"
[11] "end_lat" "end_lng" "member_casual"
> colnames(diciembre)
[1] "ride_id" "rideable_type" "started_at" "ended_at" "start_station_name"
[6] "start_station_id" "end_station_name" "end_station_id" "start_lat" "start_lng"
[11] "end_lat" "end_lng" "member_casual"
Comprobamos nuevamente nuestro conjunto de datos en busca de posibles incongruencias:
str(enero)……… (análisis de todos los meses de Enero a Diciembre)
str(diciembre)
Unimos los datos en un solo dataset , ya que no encontramos diferencias.
all_trips <- bind_rows(enero, febrero, marzo, abril, mayo, junio, julio, agosto, septiembre, octubre, noviembre, diciembre)
Se necesita añadir más columnas para tener más detalle a la hora de calcular días, meses o años, para ello añadiremos las columnas necesarias con el formato adecuado.
all_trips$date <- as.Date(all_trips$started_at) #Formato por defecto yyyy-mm-dd
all_trips$month <- format(as.Date(all_trips$date), "%m") #Extraemos el mes de la fecha en formato numérico
all_trips$day <- format(as.Date(all_trips$date), "%d") #Extraemos el día del mes
all_trips$year <- format(as.Date(all_trips$date), "%Y") #Extraemos el año
all_trips$day_of_week <- format(as.Date(all_trips$date), "%A") #Extraemos el nombre completo del día de la semana
Añadimos la columna “ride_length” en la que calcularemos la longitud de cada viaje, para ello restáremos las columnas “ended_at” y “started_at”.
all_trips$ride_length <- difftime(all_trips$ended_at, all_trips$started_at)
Convertimos la columna que acabamos de crear “ride_length” en valor numérico, para poder hacer cálculos con ella.
is.factor(all_trips$ride_length)
all_trips$ride_length <- as.numeric(as.character(all_trips$ride_length))
is.numeric(all_trips$ride_length)
Algunos cálculos en ride_length resultan negativos, debemos eliminar estos datos erróneos para que nuestro análisis sea correcto.
all_trips <- all_trips[all_trips$ride_length >= 0, ]
Análisis
Ahora analizaremos en número de viajes realizados por miembros y usuarios ocasionales. Los resultados nos muestran que hay mayor cantidad de viajes realizados por miembros 63.3% que por usuarios ocasionales 36.7%.
all_trips %>%
group_by(member_casual) %>%
summarise(number_of_rides = n(),
'perc' = (n() / nrow(all_trips)) * 100)
# A tibble: 2 × 3
member_casual number_of_rides perc
<chr> <int> <dbl>
1 casual 2151563 36.7
2 member 3708778 63.3
Ahora creamos una visualización con estos datos obtenidos:
# Agrupar y resumir los datos
summary_at <- all_trips %>%
group_by(member_casual) %>%
summarise(number_of_rides = n(),
percent = (n() / nrow(all_trips)) * 100)
# Crear gráfico de barras
ggplot(summary_df, aes(x = member_casual, y = number_of_rides, fill = member_casual)) + geom_bar(stat = "identity") + labs(title = "Número de Viajes por Tipo de Usuario",x = "Tipo de Usuario",y = "Número de Viajes") + theme_minimal()
Generamos un resumen del conjunto de datos.
summary(all_trips$ride_length)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.0 332.7 583.0 1039.1 1035.0 93596.0
Vemos que la duración máxima es extremadamente alta en ambos grupos, podría ser un error en los datos o un viaje mal registrado (por ejemplo, una bicicleta no devuelta correctamente). Por lo cual vamos a filtrar valores extremos con un límite razonable:
all_trips <- all_trips %>% filter(ride_length < 24 * 60 * 60) # Menos de 24 horas
También vemos que hay ay viajes con ride_length = 0, lo que podría indicar registros incorrectos, como, por ejemplo, errores en la recolección de datos o viajes cancelados.
Para corregir esto procederemos eliminar los registros con ride_length = 0 :
all_trips <- all_trips %>% filter(ride_length > 0)
Ahora verificamos los valores mínimos, máximos, media(promedio) y mediana.
all_trips %>%
group_by(member_casual) %>%
summarise(
mean_ride_length = mean(ride_length),
median_ride_length = median(ride_length),
max_ride_length = max(ride_length),
min_ride_length = min(ride_length)
)
Podemos ver que los usuarios casuales realizan viajes más largos con un promedio (mean) de 1509 seg mientras que los miembros realizan viajes promedio de 766 seg.
La mediana también es más alta para los usuarios casuales (723 seg vs 522 seg), lo que indica que este tipo de usuarios realizaría viajes más largos.
En conclusión, se podría decir que los usuarios casuales tienden a usar las bicicletas por más tiempo en comparación con los miembros, que realizan viajes más cortos y probablemente más frecuentes.
Al analizar el valor máximo sigue apareciendo una anomalía lo que indicaría que puede haber errores en los datos o viajes que no fueron correctamente finalizados (bicicletas no devueltas).
En cuanto a los valores mínimos aparecen valores cercanos a 0, esto podría sugerir que habría errores en la recolección de datos o que hubo viajes que fueron cancelados instantáneamente.
Los viajes de 0 segundos o cercanos a 0 deberían eliminarse para evitar afectar el análisis. Para esto filtramos los valores menores a 60 seg:
all_trips <- all_trips %>% filter(ride_length > 60)
A- Basándonos en los datos obtenidos previamente podríamos recomendarle al negocio fomentar la conversión de usuarios a casuales a miembros. Dado que los usuarios casuales hacen viajes más largos se podrían ofrecer descuentos o promociones para que sea más atractivo suscribirse al servicio.
B- Por otra parte, se podría optimizar la disponibilidad de bicicletas considerando que lo miembros realizan viajes más cortos y eficientes, lo que sugiere que se pueden redistribuir bicicletas en estaciones clave durante horas punta.
Analizamos los viajes por mes de los miembros y los usuarios casuales.
all_trips%>%
group_by(month) %>%
summarise(
count = n(),
'%' = (count / nrow(all_trips)) * 100,
members_p = mean(member_casual == "member") * 100,
casual_p = mean(member_casual == "casual") * 100,
`Member x Casual Perc Difer` = members_p - casual_p
)
Los meses con más viajes son de Mayo a Septiembre, lo que indicaría que la mayor cantidad de viajes ocurre en verano y principios de otoño.
Los meses con menor actividad son Diciembre y Enero, esto indicaría que hay menor demanda en invierno debido al clima frío.
Diferencia entre miembros y usuarios casuales:
Los miembros dominan todo el año, pero su proporción disminuye en verano.
En invierno (enero - febrero), los miembros representan más del 79% de los viajes, mientras que los usuarios casuales son menos del 21%.
De esto podemos concluir que:
A. Los usuarios casuales aumentan su demanda en verano lo que indicaría que hay más usuarios casuales que aprovechan el buen clima.
B. Los miembros son más estables, lo que sugiere que usan la bicicleta para transporte regular durante todo el año.
Recomendaciones para el negocio:
Debido que hay más usuarios casuales en verano ya que estos aumentan, se podría ofrecer promociones para que los usuarios casuales pasen a ser miembros, como por ejemplo descuento en las suscripciones.
Ya que los usuarios casuales alcanzan su máximo en verano se podría optimizar la disponibilidad de bicicletas y estaciones en zonas turísticas.
Los miembros mantienen un uso constante, son clientes más leales y recurrentes por esto es importante mejorar su experiencia constantemente, como por ejemplo con un mantenimiento eficiente y mejoras en las estaciones.
Creamos una visualización que nos muestre la variación entre miembros y usuarios casuales durante el año:
all_trips %>%
group_by(month, member_casual) %>%
summarise(count = n(), .groups = "drop") %>%
ggplot(aes(x = month, y = count, color = member_casual, group = member_casual)) +
geom_line(size = 1.2) + geom_point(size = 3) + labs(title = "Tendencia de Viajes por Mes y Tipo de Usuario", x = "Mes", y = "Número de Viajes", color = "Tipo de Usuario") + theme_minimal()
Ahora calculamos la duración promedio de los viajes (ride_length) por tipo de usuario (member_casual) y día de la semana (day_of_week)
all_trips%>%
group_by(member_casual, day_of_week) %>%
summarise(mean_ride_length = mean(ride_length, na.rm = TRUE), .groups = "drop")
Podemos ver que los usuarios casuales realizan viajes mas largos todos los días. Esto indicaría que este tipo de usuarios usan las bicicletas por más tiempo, mientras que los miembros realizan viajes más cortos y frecuentes.
Los usuarios casuales probablemente usan las bicicletas para paseos recreativos o turismo en fines de semana, por lo que sus viajes son más largos esos días.
También se podría inferir que los miembros utilizan las bicicletas principalmente como medio de transporte regular, con tiempos de viaje constantes en días laborales.
Ahora creamos una visualización con estos datos que mostrará cómo varía la duración de los viajes en cada día de la semana para usuarios casuales y miembros:
all_trips %>%
group_by(member_casual, day_of_week) %>%
summarise(mean_ride_length = mean(ride_length, na.rm = TRUE), .groups = "drop") %>%
ggplot(aes(x = day_of_week, y = mean_ride_length, fill = member_casual)) + geom_col(position = "dodge") +
labs(title = "Duración Promedio de Viajes por Día de la Semana",
x = "Día de la Semana", y = "Duración Promedio (segundos)", fill = "Tipo de Usuario") +
theme_minimal()
Ahora analizamos la cantidad de viajes (number_of_rides) y la duración promedio según el día de la semana (weekday) y el tipo de usuario (member_casual).
all_trips %>%
mutate(weekday = wday(started_at, label = TRUE)) %>%
group_by(member_casual, weekday) %>%
summarise(number_of_rides = n(),
average_duration = mean(ride_length)) %>%
arrange(member_casual, weekday)
Podemos ver que los usuarios casuales usan menos las bicicletas los fin de semana.
Los miembros usan las bicicletas principalmente como transporte diario.
Los usuarios casuales prefieren usar las bicicletas los fines de semana, lo que sugiere un uso recreativo o turístico.Se puede ver que los miembros también incrementan los viajes los fines de semana, pero siguen usándolas de forma más estable durante la semana.
En conclusión, los miembros usan las bicicletas para transporte diario, con trayectos cortos y eficientes. Mientras los usuarios casuales usan las bicicletas para viajes recreativos o turísticos (viajes más largos).
Creamos una visualización que mostrará cómo varía la duración de los viajes de usuarios casuales y miembros a lo largo de la semana:
all_trips %>%
group_by(member_casual, day_of_week) %>%
summarise(mean_ride_length = mean(ride_length, na.rm = TRUE), .groups = "drop") %>%
ggplot(aes(x = day_of_week, y = mean_ride_length, fill = member_casual)) +
geom_col(position = "dodge") +labs(title = "Duración Promedio de Viajes por Día de la Semana",x = "Día de la Semana", y = "Duración Promedio (segundos)", fill = "Tipo de Usuario") +theme_minimal()
Ahora analizamos la cantidad de viajes (number_of_rides) y la duración promedio según el día de la semana (weekday) y el tipo de usuario (member_casual).
all_trips %>%
mutate(weekday = wday(started_at, label = TRUE)) %>%
group_by(member_casual, weekday) %>%
summarise(number_of_rides = n(),
average_duration = mean(ride_length)) %>%
Podemos ver que los miembros usan las bicicletas principalmente como transporte diario.
Los usuarios casuales prefieren usar las bicicletas los fines de semana, lo que sugiere un uso recreativo o turístico.
Se puede ver que los miembros también incrementan los viajes los fines de semana, pero siguen usándolas de forma más estable durante la semana.
En conclusión, los miembros usan las bicicletas para transporte diario, con trayectos cortos y eficientes. Mientras los usuarios casuales usan las bicicletas para viajes recreativos o turísticos (viajes más largos).
Creamos una visualización que mostrará cómo varía la duración de los viajes de usuarios casuales y miembros a lo largo de la semana:
all_trips %>%
mutate(weekday = wday(started_at, label = TRUE)) %>%
group_by(member_casual, weekday) %>%
summarise(average_duration = mean(ride_length, na.rm = TRUE), .groups = "drop") %>%
ggplot(aes(x = weekday, y = average_duration, color = member_casual, group = member_casual)) +geom_line(size = 1.2) +geom_point(size = 3) +
labs(title = "Duración Promedio de Viajes por Día de la Semana", x = "Día de la Semana", y = "Duración Promedio (segundos)", color = "Tipo de Usuario") + theme_minimal()
Recomendaciones finales:
Optimizar la Disponibilidad de Bicicletas Según la Demanda:
Asegurar mayor disponibilidad de bicicletas los fines de semana en zonas turísticas y recreativas.
Redistribuir bicicletas en la mañana y tarde en zonas comerciales y residenciales para los miembros que usan la bicicleta para transporte diario.
Optimizar la reposición de bicicletas en estaciones clave antes de las horas punta.
Implementar Estrategias de Conversión para los Usuarios Casuales:
Ofrecer una prueba gratuita de 3 días como miembro después de 4 viajes en un mes.
Enviar promociones personalizadas a los usuarios casuales que usen la bicicleta más de 3 veces en un mes, con descuentos para su primera suscripción como miembro.
Proporcionar beneficios exclusivos para los miembros, como prioridad en estaciones en horas punta.
Mejorar la Experiencia del Usuario con Incentivos y Beneficios:
Crear rutas sugeridas en la app con recomendaciones de paseos en bicicleta para los fines de semana.
Ofrecer tarifas especiales para recorridos largos los sábados y domingos.
Implementar un programa de recompensas donde los usuarios casuales puedan obtener descuentos por usar la bicicleta más de cierto número de veces al mes.
Implementar un plan de pago por uso para usuarios casuales con una tarifa reducida para viajes de menos de 15 minutos y una tarifa más alta para viajes largos.
Finalmente, en base a los datos arrojados en el análisis realizado, se puede recomendar una campaña de Marketing basada en datos, como, por ejemplo:
Lanzar campañas de email marketing y notificaciones en la app con mensajes segmentados:
Para los usuarios casuales los viernes enviar el mensaje de: “Este fin de semana, explora la ciudad en bicicleta con nuestra promoción especial.”
Para los miembros los lunes enviar el mensaje de : “Optimiza tu ruta diaria con nuestras bicicletas en estaciones clave.”
Usar anuncios en redes sociales dirigidos a turistas o nuevos usuarios para probar el servicio.
Ofrecer promociones en eventos deportivos, festivales o actividades al aire libre para incentivar el uso de bicicletas.