Cyclistic es una empresa de bicicletlas compartidas en chicago, la cual quiere maximizar la cantidad de membresías anuales, por lo tanto, debemos de encontrar las diferencias que existen entre los cyclistas anuales y los ocasionales para diseñar una estrategía de marketing.
Nuestra tarea es descubrir en qué se diferencian los cyclistas socios anuales y los ciclistas ocasionales con respecto al uso de las bicicletas de cyclistic.
¿En qué se diferencian los socios anuales y los ciclistas ocasionales con respecto al uso de las bicicletas de Cyclistic?
Tenemos un conjunto de datos de los últimos 12 meses de viajes de cyclistic, los vamos a limpiar y tranformar.
Cargamos las librerías necesarias.
Vamos a cargar los datos de los 12 meses y los unimos en un solo conjunto de datos:
enero <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\enero2022.csv")
febrero <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\febrero2022.csv")
marzo <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\marzo2022.csv")
abril <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\abril2022.csv")
mayo <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\mayo2022.csv")
junio <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\junio2022.csv")
julio <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\julio2022.csv")
agosto <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\agosto2022.csv")
sept2021 <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\septiembre2021.csv")
oct2021 <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\octubre2021.csv")
nov2021 <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\noviembre2021.csv")
dic2021 <- read.csv("D:\\Desktop\\CursoAD\\Caso_Practico_1_Archivos\\2021-2022\\diciembre2021.csv")
c_1 <- rbind(enero,febrero,marzo,abril,mayo,junio,julio,agosto,sept2021,oct2021,nov2021,dic2021)
Observamos el conjunto:
summary(c_1)
## ride_id rideable_type started_at ended_at
## Length:5883043 Length:5883043 Length:5883043 Length:5883043
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## start_station_name start_station_id end_station_name end_station_id
## Length:5883043 Length:5883043 Length:5883043 Length:5883043
## Class :character Class :character Class :character Class :character
## Mode :character Mode :character Mode :character Mode :character
##
##
##
##
## start_lat start_lng end_lat end_lng
## Min. :41.64 Min. :-87.84 Min. :41.39 Min. :-88.97
## 1st Qu.:41.88 1st Qu.:-87.66 1st Qu.:41.88 1st Qu.:-87.66
## Median :41.90 Median :-87.64 Median :41.90 Median :-87.64
## Mean :41.90 Mean :-87.65 Mean :41.90 Mean :-87.65
## 3rd Qu.:41.93 3rd Qu.:-87.63 3rd Qu.:41.93 3rd Qu.:-87.63
## Max. :45.64 Max. :-73.80 Max. :42.37 Max. :-87.50
## NA's :5727 NA's :5727
## member_casual
## Length:5883043
## Class :character
## Mode :character
##
##
##
##
colnames(c_1)
## [1] "ride_id" "rideable_type" "started_at"
## [4] "ended_at" "start_station_name" "start_station_id"
## [7] "end_station_name" "end_station_id" "start_lat"
## [10] "start_lng" "end_lat" "end_lng"
## [13] "member_casual"
str(c_1)
## 'data.frame': 5883043 obs. of 13 variables:
## $ ride_id : chr "C2F7DD78E82EC875" "A6CF8980A652D272" "BD0F91DFF741C66D" "CBB80ED419105406" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "classic_bike" "classic_bike" ...
## $ started_at : chr "2022-01-13 11:59:47" "2022-01-10 08:41:56" "2022-01-25 04:53:40" "2022-01-04 00:18:04" ...
## $ ended_at : chr "2022-01-13 12:02:44" "2022-01-10 08:46:17" "2022-01-25 04:58:01" "2022-01-04 00:33:00" ...
## $ start_station_name: chr "Glenwood Ave & Touhy Ave" "Glenwood Ave & Touhy Ave" "Sheffield Ave & Fullerton Ave" "Clark St & Bryn Mawr Ave" ...
## $ start_station_id : chr "525" "525" "TA1306000016" "KA1504000151" ...
## $ end_station_name : chr "Clark St & Touhy Ave" "Clark St & Touhy Ave" "Greenview Ave & Fullerton Ave" "Paulina St & Montrose Ave" ...
## $ end_station_id : chr "RP-007" "RP-007" "TA1307000001" "TA1309000021" ...
## $ start_lat : num 42 42 41.9 42 41.9 ...
## $ start_lng : num -87.7 -87.7 -87.7 -87.7 -87.6 ...
## $ end_lat : num 42 42 41.9 42 41.9 ...
## $ end_lng : num -87.7 -87.7 -87.7 -87.7 -87.6 ...
## $ member_casual : chr "casual" "casual" "member" "casual" ...
Buscamos y exploramos valores vacíos o en blanco:
colSums(c_1=="")
## ride_id rideable_type started_at ended_at
## 0 0 0 0
## start_station_name start_station_id end_station_name end_station_id
## 884365 884363 946303 946303
## start_lat start_lng end_lat end_lng
## 0 0 NA NA
## member_casual
## 0
Observamos que hay entradas en blanco, los convertimos a valores NA para eliminarlos. Al ser un conjunto de datos ficticio, queda a mi criterio el tratamiento de valores nulos.
c_1[c_1==""] <- NA
Observamos que el cambio se haya realizado correctamente
apply(is.na(c_1),2,sum)
## ride_id rideable_type started_at ended_at
## 0 0 0 0
## start_station_name start_station_id end_station_name end_station_id
## 884365 884363 946303 946303
## start_lat start_lng end_lat end_lng
## 0 0 5727 5727
## member_casual
## 0
Eliminamos los valores nulos y comprobamos que ya no estén:
c_2 <- na.omit(c_1)
sum(is.na(c_2))
## [1] 0
Comprobamos que ya no haya valores nulos
apply(is.na(c_2),2,sum)
## ride_id rideable_type started_at ended_at
## 0 0 0 0
## start_station_name start_station_id end_station_name end_station_id
## 0 0 0 0
## start_lat start_lng end_lat end_lng
## 0 0 0 0
## member_casual
## 0
Borramos las columnas que considero no necesito para el análisis por ahora:
c_3 <- c_2 %>%
select(-c(start_lat, start_lng, end_lat, end_lng))
Cambiamos las columnas started_at y ended_at a formato ymd_hms:
col_started <- ymd_hms(c_3$started_at)
col_ended <- ymd_hms(c_3$ended_at)
#quitamos las columnas con el formato chr
c_4 <- select(c_3, -ended_at, -started_at)
#agregamos las columnas con el formato ymd:hms al conjunto de datos
c_5 <- c_4 %>% mutate(started_at = col_started)%>%
mutate(ended_at = col_ended)
c_5[1:5,8:9]
## started_at ended_at
## 1 2022-01-13 11:59:47 2022-01-13 12:02:44
## 2 2022-01-10 08:41:56 2022-01-10 08:46:17
## 3 2022-01-25 04:53:40 2022-01-25 04:58:01
## 4 2022-01-04 00:18:04 2022-01-04 00:33:00
## 5 2022-01-20 01:31:10 2022-01-20 01:37:12
Creamos la columna “duración viaje” restando a started_at, ended_at. Se crea en segundos pero para fines visuales, también creamos una en formato hms:
c_6 <- c_5 %>% mutate(duracion_viaje_secs = ended_at - started_at)
c_7 <- c_6 %>% mutate(duracion_viaje = as.hms(ended_at - started_at))
c_7[1:5,9:11]
## ended_at duracion_viaje_secs duracion_viaje
## 1 2022-01-13 12:02:44 177 secs 00:02:57
## 2 2022-01-10 08:46:17 261 secs 00:04:21
## 3 2022-01-25 04:58:01 261 secs 00:04:21
## 4 2022-01-04 00:33:00 896 secs 00:14:56
## 5 2022-01-20 01:37:12 362 secs 00:06:02
Creamos una columna con los días de la semana de los viajes, empezando 1 en domingo y 7 sábado. De igual manera creamos una en formato chr:
c_8 <- c_7 %>% mutate(dia_semana = (as.POSIXlt(c_5$started_at)$wday+1)) %>%
mutate(dia = (weekdays(c_5$started_at)))
c_8[1:5,10:13]
## duracion_viaje_secs duracion_viaje dia_semana dia
## 1 177 secs 00:02:57 5 jueves
## 2 261 secs 00:04:21 2 lunes
## 3 261 secs 00:04:21 3 martes
## 4 896 secs 00:14:56 3 martes
## 5 362 secs 00:06:02 5 jueves
Creamos una columna para extraer los meses de los viajes:
c_9 <- c_8%>%
mutate(mes_letra = format(c_6$started_at, "%B"))
c_9[1:5,11:14]
## duracion_viaje dia_semana dia mes_letra
## 1 00:02:57 5 jueves enero
## 2 00:04:21 2 lunes enero
## 3 00:04:21 3 martes enero
## 4 00:14:56 3 martes enero
## 5 00:06:02 5 jueves enero
Creamos una columna para la temporada de los viajes de acuerdo al mes:
c_10 <- c_9 %>%
mutate(temporada = case_when(
(mes_letra == "diciembre") | (mes_letra == "enero")~ "invierno",
(mes_letra == "marzo") | (mes_letra == "abril") ~ "primavera",
(mes_letra == "junio") | (mes_letra == "julio") ~ "verano",
(mes_letra == "febrero") ~ "invierno",
(mes_letra == "mayo") ~ "primavera",
(mes_letra == "agosto") ~ "verano",
(mes_letra == "noviembre") ~ "otoño",
(mes_letra == "septiembre") | (mes_letra == "octubre") ~ "otoño"))
c_10[1:5,13:15]
## dia mes_letra temporada
## 1 jueves enero invierno
## 2 lunes enero invierno
## 3 martes enero invierno
## 4 martes enero invierno
## 5 jueves enero invierno
Revisamos que todos los meses sean proporcionales a la cantidad de variables;
length(c_10$temporada [c_10$temporada == "primavera"])
## [1] 991088
length(c_10$temporada [c_10$temporada == "verano"])
## [1] 1868355
length(c_10$temporada [c_10$temporada == "otoño"])
## [1] 1355026
length(c_10$temporada [c_10$temporada == "invierno"])
## [1] 345677
Comparamos a los miembros anuales con los ciclistas ocasionales:
aggregate(c_10$duracion_viaje ~ c_10$member_casual, FUN = mean)
## c_10$member_casual c_10$duracion_viaje
## 1 casual 1547.2736 secs
## 2 member 752.7223 secs
aggregate(c_10$duracion_viaje ~ c_10$member_casual, FUN = median)
## c_10$member_casual c_10$duracion_viaje
## 1 casual 00:14:41
## 2 member 00:09:07
aggregate(c_10$duracion_viaje ~ c_10$member_casual, FUN = max)
## c_10$member_casual c_10$duracion_viaje
## 1 casual 2442301 secs
## 2 member 89575 secs
aggregate(c_10$duracion_viaje ~ c_10$member_casual, FUN = min)
## c_10$member_casual c_10$duracion_viaje
## 1 casual -7621 secs
## 2 member -7745 secs
Nos damos cuenta que hay viajes en negativo, decidimos eliminarlos
Eliminar viajes con valores negativos e iguales a 0:
cyclistic <- c_10[!(c_10$start_station_name == "HQ QR" | c_10$duracion_viaje_secs<=0),]
Media duración de los viajes:
as.hms(mean(cyclistic$duracion_viaje_secs))
## 00:18:00.034791
mean(cyclistic$duracion_viaje)
## Time difference of 1080.035 secs
Observamos las modas:
mfv(cyclistic$dia)
## [1] "sábado"
mfv(cyclistic$mes_letra)
## [1] "julio"
mfv(cyclistic$temporada)
## [1] "verano"
Cálculamos el promedio de duración de viaje por tipo de ciclistas:
aggregate(cyclistic$duracion_viaje_secs~member_casual,cyclistic, mean,na.rm=TRUE)
## member_casual cyclistic$duracion_viaje_secs
## 1 casual 1547.4104 secs
## 2 member 752.7899 secs
Tiempo de viaje promedio por día por cada tipo de ciclista:
aggregate(cyclistic$duracion_viaje ~ cyclistic$member_casual + cyclistic$dia, FUN = mean)
## cyclistic$member_casual cyclistic$dia cyclistic$duracion_viaje
## 1 casual domingo 1783.4258 secs
## 2 member domingo 848.0927 secs
## 3 casual jueves 1366.4828 secs
## 4 member jueves 722.5699 secs
## 5 casual lunes 1606.6642 secs
## 6 member lunes 729.6108 secs
## 7 casual martes 1354.4807 secs
## 8 member martes 708.7854 secs
## 9 casual miércoles 1324.9922 secs
## 10 member miércoles 715.2554 secs
## 11 casual sábado 1703.4030 secs
## 12 member sábado 845.2656 secs
## 13 casual viernes 1441.8493 secs
## 14 member viernes 736.1187 secs
Porcentaje de ciclistas, tiempo promedio de viaje por minutos y bicicletas preferidas:
Top cinco de estaciones de inicio y de final más concurridas:
Viajes por mes y promedio de tiempo en minutos:
Viajes realizados por día y promedio de tiempo en minutos:
Tres recomendaciones que pude observar a partir del comportamiento de los datos:
Lanzar la campaña de marketing para usuarios casuales empezando la temporada de verano, que abarca los meses junio, julio, agosto y septiembre, así como en los días viernes, sábado y domingo.
Enfatizar la campaña de marketing en el uso de la bicicleta clásica qué es la preferida por los ciclistas casuales.
Agregar promociones para los miembros anuales que viajen más de 15 minutos, ya que los usuarios casuales suelen realizar viajes más largos a partir de los minutos ya mencionados y puede interesarles la membresía anual al contar con esa promoción.
Colocar publicidad en las estaciones de inicio y de final más concurridas por los ciclistas casuales:
Street Dr & Grand Ave
Dusable Lake Shore Dr Monroe St
Dusable Lake Shore Dr & North Blvd
Millennium Park
Michigan Ave & Oak St
Conjuntos de datos abiertos, bajo la licencia Motivate, almacenados en: https://divvy-tripdata.s3.amazonaws.com/index.html
Mariana Raquel Flores Carrillo ir a linkedin: https://www.linkedin.com/in/mariana-raquel-flores-carrillo-20201b247/