Cyclistic, es una empresa ficticia, dedica al servicio de bicicletas compartidas en la mayoria de estaciones de la ciudad de Chicago, durante algunos años su trayectora ha tenido exito, con las bicicletas compartidas, las mismas que estan equipadas con geolocalizadores y sistema de desbloqueo en cada estacion.
Su declaracion de empresa, se basa en crear conciencia general del uso de bicicleta compartidas, atrayendo un gran segmento de consumidores. Un enfoque que hace posible, que sus planes de precios sean adecuados, existe membresias anuales, que permite ser miembro anual de Cyclistic y otro para ciclista ocasional por dia.
Parte de la estrategia, ha sido el uso efectivo de redes sociales. Su Gerente y Directora de Marketing, esta comprometida en desarrollar campaña, para impulsar a los clientes ocasionales en miembros anuales. Para cerciorarse, ha encargado a su equipo de analistas de datos, buscar un paramentro o tendencia sobre los datos que proporciona la empresa Motivate International Inc. quien ha puesto a disposición los datos bajo esta licencia, son datos publicos.
En este apartado se incluiye cuenstionario sobre el caso de estudio, el cual hay que responder, que es parte de Coursera en el programa de Google para Certificacion de Analista de Datos Junior.
1. ¿En qué se diferencian los usuarios anuales y los ciclistas ocasionales al usar las bicicletas de Cyclistic?
Los clientes que compran pases de un solo viaje o de un día completo se conocen como ciclistas ocasionales. Los clientes que adquieren membresías anuales son miembros de Cyclistic.
2. ¿Por qué los ciclistas ocasionales comprarían membresías anuales de Cyclistic?
Su flexibilidad de precios ayuda a Cyclistic a atraer más clientes, Moreno cree que maximizar el número de miembros anuales será clave para el crecimiento futuro.
3. ¿Cómo puede Cyclistic usar los medios digitales para influenciar a los ciclistas ocasionales para que se conviertan en miembros?
Lily Moreno: La directora de marketing y su gerente. Moreno es responsable del desarrollo de campañas e iniciativas para promover el programa de bicicletas compartidas. Estas pueden incluir correo electrónico, redes sociales y otros canales.
La estrategia de marketing de Cyclistic se basó en crear conciencia general y atraer a amplios segmentos de consumidores. Un enfoque que ayudó a hacer posibles estas cosas fue la flexibilidad de sus planes de precios: pases de un solo viaje, pases de un día completo y membresías anuales. Los clientes que compran pases de un solo viaje o de un día completo se conocen como ciclistas ocasionales. Los clientes que adquieren membresías anuales son miembros de Cyclistic.
4. Moreno te ha asignado la primera pregunta para responder: ¿Cómo usan las bicicletas Cyclistic los miembros anuales y los ciclistas ocasionales de manera diferente?
Cyclistic se distingue al ofrecer también bicicletas reclinables, triciclos de mano y bicicletas de carga, lo que hace que las bicicletas compartidas sean más inclusivas para las personas con discapacidades y los ciclistas que no pueden usar una bicicleta estándar de dos ruedas. La mayoría de los ciclistas optan por las bicicletas tradicionales; alrededor del 8% de los ciclistas usan las opciones de asistencia. Los usuarios de Cyclistic son más propensos a montar en bicicleta por ocio, pero alrededor del 30% usa las bicicletas para viajar al trabajo todos los días.
Cyclistic lanzó una exitosa oferta de bicicletas compartidas. Desde entonces, el programa ha crecido a una flota de 5,824 bicicletas que están geolocalizadas y bloqueadas en una red de 692 estaciones en Chicago.Aproximadamente un promedio de 8 bicicletas por estación. Las bicicletas se pueden desbloquear en una estación y devolver a cualquier otra estación en el sistema en cualquier momento.
5. Una declaración clara de la tarea comercial
Cyclistic es un programa con un equipo que trabaja para generar conciencia del uso de bicicletas compartidas, sirviendo fielmente a cada uno de sus clientes.
6. Una descripción de todas las fuentes de datos utilizadas
La utilización de datos históricos de viajes de Cyclistic para analizar se realizó la descarga de los datos de viajes de los clientes de Cyclistic datos Divvy_2019_Q1 y Divvy_2020_Q1 . Los mismo que viene en formato .csv (Valores separados por coma). La empresa Motivate International Inc. es propietaria bajo licencia, estos datos son de exploración para fines de estudio.
7. ¿Cuál es el problema que estás tratando de resolver?
¿Por qué los ciclistas ocasionales comprarían membresías anuales de Cyclistic?
8. ¿Cómo pueden tus conocimientos impulsar las decisiones comerciales?
Dando valor a los datos como Analista de Datos para descubrir tendencias o parámetros, que sea relevante e importante para la toma de decisiones, de acuerdo a la información proporcionada.
9. ¿Dónde se encuentran sus datos?
Los datos fueron descargados de Coursera en formato .csv son 2 archivos Divvy_Trips_2019_Q1.csv y Divvy_Trips_2020_Q1.CSV los cuales se encuentran descargado y archivados en google drive y google sheet personal, en Google Drive también están respaldados los originales en .csv
10. ¿Cómo están organizados los datos?
Cada archivo está organizado por columnas iniciando con una columnas identificadoras, y por filas en un formato que esta determinado, sin embargo su cantidad de columnas entre las dos archivos difiere la Divvy_Trips_2019_Q1 tiene 12 columnas mientras que Divvy_Trips_2020_Q1 contiene 13 columnas, ambas son estructurada.Ambas tablas tiene formatos: cualitativos ; cuantitativos ; discretos, continuos, fraccionados.
11. ¿Hay problemas de sesgo o credibilidad en estos datos? ¿Sus datos ROCCC?
Con la observación de datos, confirman que no está completo algunas celdas de las columnas, se presentan como vacías.
Considero que en la credibilidad de los datos, existen algunas incoherencias en algunos registros por Ejemplo: el uso de la bicicleta por dos segundos.
A pesar de que viene de una fuente de datos de primer instancia , su información es considerada como confiable, actual percibiendo errores humanos o de programa.
12. ¿Cómo está abordando las licencias, la privacidad, la seguridad y la accesibilidad?
Los conjuntos de datos tienen un nombre diferente porque Cyclistic es una empresa ficticia. Para los fines de este estudio de caso, los conjuntos de datos son apropiados y le permitirán responder a las preguntas comerciales. Motivate International Inc. ha puesto a disposición los datos bajo esta licencia).
Estos son datos públicos que puede utilizar para explorar cómo los diferentes tipos de clientes utilizan las bicicletas Cyclistic. Los problemas de privacidad de los datos le prohíben utilizar la información de identificación personal de los ciclistas. Esto significa que no podrá conectar las compras de pases con los números de tarjetas de crédito para determinar si los ciclistas ocasionales viven en el área de servicio de Cyclistic o si han comprado varios pases individuales.
13. ¿Cómo verificó la integridad de los datos?
Encontrar en las tablas la existencia de errores, inconsistencia en dos datos o falta de datos, es la primera visualización.
14. ¿Cómo le ayuda a responder su pregunta?
A pesar de que los datos tengan licencia y al mismo tiempo errores e inconsistencia en los datos, considero que hay aún datos significativos que permiten determinar una tendencia para analizar y que genere valor a la toma de decisiones para responde a la tarea de la empresa por medio de datos.
15. ¿Hay algún problema con los datos?
listado: A. Archivos tiene diferentes encabezados o títulos de columnas diferentes B. Cada archivo está generado sus columnas con distinto argumento, al igual que sus registros. C. Inconsistencia en los registros por ejemplo el uso de bicicleta por cuatros segundos D. Celdas vacías E.número de columnas varía por archivo. F. Formatos diferentes
16. ¿Qué herramientas está eligiendo y por qué?
Para este proyecto, he recurrido al uso de Google Sheets, Documents.herramientas que estan en la nube, permitiendo conocer su uso a largo del proceso, con Google Sheets he podido descargar los archivos csv respectivos, con los cuales se realizó tabla dinámica, al mismo tiempo, me permite conectarme con BigQuery, para formatear los archivos y al mismo tiempo para consolidarlos en uno solo, posterior a ello he utilizado Rstudio de escritorio y continuar con un dashboard en Tableau
17. ¿Ha asegurado la integridad de sus datos? Se normalizo las tablas de manera adecuada con el fin de poder analizar las mismas que posteriormente se consolido en uno solo archivo para poder analizar con el propósito de cumplir el objetivo de la empresa, quien proporciona los datos.
La importancia de preparacion de datos, permite que buscar, la manera de tratar los propositos entregando resultado sobre el estudio del caso, lo realice varias practicas en diferentes herramientas.
Primero en Google Sheet, para ver como se comportaba los
archivos dentro dentro de Google Sheet, posterior visualice tipo de
formatos de cada columna, posterior realice modificacion de tipos de
formatos y luego calculos individualemte de cada tabla, para continuar
con la consolide de manera apilada mediante conexion de Google Drive
Segundo use Bigquery en el cual cargue los archivos
individualmente .csv y posterior genere dentro de mi proyectos la
consolidacion de los dos archivos
Tercero el uso de R en RStudio, en el cual cargue los datos
de la fuente, que proporciono Coursera, es aqui donde mas enfasis he
puesto para el estudio, y lo que al igual que en otras plataformas
realice un analisis individual de cada tabla, para posterior analizarlo
de forma consolidada apilado a lo largo, al inicio se vera algunos
cambios en las dos tablas pero por la diferencia de
informacion que tenia cada tabla realice primero la del año 2019 y
posterior la tabla 2020, para luego consolidar entre tablas.
library(purrr)
Mi_Lib <- c("tidyverse","lubridate", "dplyr","tableone","naniar", "stringi",
"readr", "tidyr","ggplot2", "scales", "patchwork", "purrr" )
purrr::walk(Mi_Lib, ~ library(.x, character.only = TRUE))## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.1 ✔ stringr 1.6.0
## ✔ ggplot2 4.0.0 ✔ tibble 3.3.0
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
##
## Adjuntando el paquete: 'scales'
##
##
## The following object is masked from 'package:readr':
##
## col_factor
##
##
## The following object is masked from 'package:purrr':
##
## discard
Descargamos del folder de descarga los archivos en la carpeta datos original pestaña File-> import datase ->From texT (readr)->browser->busca la carpeta o archivo click en import Divvy_Trips_2019_Q1
## Rows: 365069 Columns: 12
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): from_station_name, to_station_name, usertype, gender
## dbl (5): trip_id, bikeid, from_station_id, to_station_id, birthyear
## num (1): tripduration
## dttm (2): start_time, end_time
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Lo mismo para Divvy_Trips_2020_Q1
## Rows: 426887 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (5): ride_id, rideable_type, start_station_name, end_station_name, memb...
## dbl (6): start_station_id, end_station_id, start_lat, start_lng, end_lat, e...
## dttm (2): started_at, ended_at
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Visual Divvy_Trips_2019_Q1
Visual Divvy_Trips_2020_Q1
Luego de visualizar los conjuntos de datos veremos sus cabezerass head(), dimension dim() variables names(), y estructura str() de cada tabla. Con la funcion head() visualizamos los nombres de la variables o columnas, ademas de un pequeño resumen de la informtacion que contine cada tabla head(Divvy_Trips_2019_Q1)
Cabeceras de variables Divvy_Trips_2019_Q1
Cabeceras de variables Divvy_Trips_2020_Q1
Con la funcion dim() muestra el numero total de registros o filas y el numero de columnas o variables
Numero de registros Divvy_Trips_2019_Q1
## [1] 365069 12
Numero de registros Divvy_Trips_2020_Q1
## [1] 426887 13
Muestra el nombre de cada columna o variable d laa tabla
Nombres de variables Divvy_Trips_2019_Q1
## [1] "trip_id" "start_time" "end_time"
## [4] "bikeid" "tripduration" "from_station_id"
## [7] "from_station_name" "to_station_id" "to_station_name"
## [10] "usertype" "gender" "birthyear"
Nombres de variables Divvy_Trips_2020_Q1
## [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"
Como podemos ver que los nombres de las variables son distintas y pero hay similitud en ciertas variables o columnas, con registros sinonimos
Estructura Divvy_Trips_2019_Q1
## spc_tbl_ [365,069 × 12] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ trip_id : num [1:365069] 21742443 21742444 21742445 21742446 21742447 ...
## $ start_time : POSIXct[1:365069], format: "2019-01-01 00:04:37" "2019-01-01 00:08:13" ...
## $ end_time : POSIXct[1:365069], format: "2019-01-01 00:11:07" "2019-01-01 00:15:34" ...
## $ bikeid : num [1:365069] 2167 4386 1524 252 1170 ...
## $ tripduration : num [1:365069] 390 441 829 1783 364 ...
## $ from_station_id : num [1:365069] 199 44 15 123 173 98 98 211 150 268 ...
## $ from_station_name: chr [1:365069] "Wabash Ave & Grand Ave" "State St & Randolph St" "Racine Ave & 18th St" "California Ave & Milwaukee Ave" ...
## $ to_station_id : num [1:365069] 84 624 644 176 35 49 49 142 148 141 ...
## $ to_station_name : chr [1:365069] "Milwaukee Ave & Grand Ave" "Dearborn St & Van Buren St (*)" "Western Ave & Fillmore St (*)" "Clark St & Elm St" ...
## $ usertype : chr [1:365069] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ gender : chr [1:365069] "Male" "Female" "Female" "Male" ...
## $ birthyear : num [1:365069] 1989 1990 1994 1993 1994 ...
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Estructura Divvy_Trips_2020_Q1
## spc_tbl_ [426,887 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ ride_id : chr [1:426887] "EACB19130B0CDA4A" "8FED874C809DC021" "789F3C21E472CA96" "C9A388DAC6ABF313" ...
## $ rideable_type : chr [1:426887] "docked_bike" "docked_bike" "docked_bike" "docked_bike" ...
## $ started_at : POSIXct[1:426887], format: "2020-01-21 20:06:59" "2020-01-30 14:22:39" ...
## $ ended_at : POSIXct[1:426887], format: "2020-01-21 20:14:30" "2020-01-30 14:26:22" ...
## $ start_station_name: chr [1:426887] "Western Ave & Leland Ave" "Clark St & Montrose Ave" "Broadway & Belmont Ave" "Clark St & Randolph St" ...
## $ start_station_id : num [1:426887] 239 234 296 51 66 212 96 96 212 38 ...
## $ end_station_name : chr [1:426887] "Clark St & Leland Ave" "Southport Ave & Irving Park Rd" "Wilton Ave & Belmont Ave" "Fairbanks Ct & Grand Ave" ...
## $ end_station_id : num [1:426887] 326 318 117 24 212 96 212 212 96 100 ...
## $ start_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ start_lng : num [1:426887] -87.7 -87.7 -87.6 -87.6 -87.6 ...
## $ end_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ end_lng : num [1:426887] -87.7 -87.7 -87.7 -87.6 -87.6 ...
## $ member_casual : chr [1:426887] "member" "member" "member" "member" ...
## - attr(*, "spec")=
## .. cols(
## .. ride_id = col_character(),
## .. rideable_type = col_character(),
## .. started_at = col_datetime(format = ""),
## .. ended_at = col_datetime(format = ""),
## .. start_station_name = col_character(),
## .. start_station_id = col_double(),
## .. end_station_name = col_character(),
## .. end_station_id = col_double(),
## .. start_lat = col_double(),
## .. start_lng = col_double(),
## .. end_lat = col_double(),
## .. end_lng = col_double(),
## .. member_casual = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
Muestra la estructura de cada tabla este momento me encuentro en la fase para procesar los datos nuevamene llamare a mis dos tablas para prosesar
Creamos la columna con nombre ride_length en Divvy_Trips_2019_Q1 que
contega
la diferencia de tiempo entre las columnas end_time y start_time y en la
tabla Divvy_Trips_2020_Q1 se encuentra las columnas ended_at y
started_at para encontrar su diferencia de tiempo, tambien con el nombre
ride_length. En este caso entre las columnas usamos la funcion
as.Date(), por ser formato de fecha y hora distinta clase POSIXct , lo
que causaba un error al hacerlo de manera simple. Ademas permite
mantener el mismo formato.
Divvy_Trips_2019_Q1$ride_length <-
(Divvy_Trips_2019_Q1$end_time) -
( Divvy_Trips_2019_Q1$start_time)Visual
Divvy_Trips_2020_Q1$ride_length <-
(Divvy_Trips_2020_Q1$ended_at) -
( Divvy_Trips_2020_Q1$started_at)Visual
Para que sea coherente entre las tablas Divvy_Trips_2019_Q1 se convirtio la columna ride_length de minutos a segundo con la finalidad de tener igualdad de tiempos con la tabla Divvy_Trips_2020_Q1.
CONVERSION
Visual
Realizaremos el calculo para obtener el dia de la semana incluyendo el nombre columna llamada week_day para ello usaremos la columna de la tabla Divvy_Trips_2019_Q1 start_time, lo mismo para la tabla Divvy_Trips_2020_Q1 con columna started_at Usamos la funcion week() para obtener el nombre del dia de la semana
Dia de semana Divvy_Trips_2019_Q1
Dia de semana Divvy_Trips_2020_Q1
Para tener un poco de coherencia entre tablas se creo en cada una de las columnas que facilitan el analisis es asi que Divvy_Trips_2019_Q1 y en Divvy_Trips_2020_Q1 se creo el nombre num_week_day para poner el numero de dia de la semana, si nos fijamos obtubo el dato de la columna start_time en la tabla Divvy_Trips_2019_Q1 y started_at de la tabla Divvy_Trips_2019_Q1,
Numero de dia de la semana Divvy_Trips_2019_Q1
Numero de dia de la semana Divvy_Trips_2020_Q1
Posterior se verifico su estructura con str en cada una de ellas y tambien en la parte superior del Script con View()
Estructura
## spc_tbl_ [365,069 × 15] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ trip_id : num [1:365069] 21742443 21742444 21742445 21742446 21742447 ...
## $ start_time : POSIXct[1:365069], format: "2019-01-01 00:04:37" "2019-01-01 00:08:13" ...
## $ end_time : POSIXct[1:365069], format: "2019-01-01 00:11:07" "2019-01-01 00:15:34" ...
## $ bikeid : num [1:365069] 2167 4386 1524 252 1170 ...
## $ tripduration : num [1:365069] 390 441 829 1783 364 ...
## $ from_station_id : num [1:365069] 199 44 15 123 173 98 98 211 150 268 ...
## $ from_station_name: chr [1:365069] "Wabash Ave & Grand Ave" "State St & Randolph St" "Racine Ave & 18th St" "California Ave & Milwaukee Ave" ...
## $ to_station_id : num [1:365069] 84 624 644 176 35 49 49 142 148 141 ...
## $ to_station_name : chr [1:365069] "Milwaukee Ave & Grand Ave" "Dearborn St & Van Buren St (*)" "Western Ave & Fillmore St (*)" "Clark St & Elm St" ...
## $ usertype : chr [1:365069] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ gender : chr [1:365069] "Male" "Female" "Female" "Male" ...
## $ birthyear : num [1:365069] 1989 1990 1994 1993 1994 ...
## $ ride_length : 'difftime' num [1:365069] 390 441 829 1783 ...
## ..- attr(*, "units")= chr "mins"
## $ week_day : chr [1:365069] "martes" "martes" "martes" "martes" ...
## $ num_week_day : num [1:365069] 3 3 3 3 3 3 3 3 3 3 ...
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Estructura
## spc_tbl_ [426,887 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ ride_id : chr [1:426887] "EACB19130B0CDA4A" "8FED874C809DC021" "789F3C21E472CA96" "C9A388DAC6ABF313" ...
## $ rideable_type : chr [1:426887] "docked_bike" "docked_bike" "docked_bike" "docked_bike" ...
## $ started_at : POSIXct[1:426887], format: "2020-01-21 20:06:59" "2020-01-30 14:22:39" ...
## $ ended_at : POSIXct[1:426887], format: "2020-01-21 20:14:30" "2020-01-30 14:26:22" ...
## $ start_station_name: chr [1:426887] "Western Ave & Leland Ave" "Clark St & Montrose Ave" "Broadway & Belmont Ave" "Clark St & Randolph St" ...
## $ start_station_id : num [1:426887] 239 234 296 51 66 212 96 96 212 38 ...
## $ end_station_name : chr [1:426887] "Clark St & Leland Ave" "Southport Ave & Irving Park Rd" "Wilton Ave & Belmont Ave" "Fairbanks Ct & Grand Ave" ...
## $ end_station_id : num [1:426887] 326 318 117 24 212 96 212 212 96 100 ...
## $ start_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ start_lng : num [1:426887] -87.7 -87.7 -87.6 -87.6 -87.6 ...
## $ end_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ end_lng : num [1:426887] -87.7 -87.7 -87.7 -87.6 -87.6 ...
## $ member_casual : chr [1:426887] "member" "member" "member" "member" ...
## $ ride_length : 'difftime' num [1:426887] 451 223 171 529 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : chr [1:426887] "martes" "jueves" "jueves" "lunes" ...
## $ num_week_day : num [1:426887] 3 5 5 2 5 6 6 6 6 6 ...
## - attr(*, "spec")=
## .. cols(
## .. ride_id = col_character(),
## .. rideable_type = col_character(),
## .. started_at = col_datetime(format = ""),
## .. ended_at = col_datetime(format = ""),
## .. start_station_name = col_character(),
## .. start_station_id = col_double(),
## .. end_station_name = col_character(),
## .. end_station_id = col_double(),
## .. start_lat = col_double(),
## .. start_lng = col_double(),
## .. end_lat = col_double(),
## .. end_lng = col_double(),
## .. member_casual = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
Visualiza
Visuliza
Se genera una columna de “edad_cliente”, tomando de la tabla Divvy_Trips_2019_Q1, la columna “birthyear” restada el año 2025.
Se elimina de la tabla Divvy_Trips_2020 la columna
rideable_type
se debe a que solo hace ruido, no tiene informacion adecuada para un
analisis Llamamos la funcion colnames() para asegurarnos cual es el
nombre de columna que se va eliminar
## [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" "ride_length" "week_day"
## [16] "num_week_day"
Posterior realizamos a eliminacion
Nuevamente llamamos a la funcion colnames() y tambien lo visualizamos
## [1] "ride_id" "started_at" "ended_at"
## [4] "start_station_name" "start_station_id" "end_station_name"
## [7] "end_station_id" "start_lat" "start_lng"
## [10] "end_lat" "end_lng" "member_casual"
## [13] "ride_length" "week_day" "num_week_day"
View(Divvy_Trips_2020_Q1)
## [1] "ride_id" "started_at" "ended_at"
## [4] "start_station_name" "start_station_id" "end_station_name"
## [7] "end_station_id" "start_lat" "start_lng"
## [10] "end_lat" "end_lng" "member_casual"
## [13] "ride_length" "week_day" "num_week_day"
La Tabla Divvy_Trips_2019_Q1 se cambiara el tipo de formato de numero a texto de la columna trip_id es numerico y cuando queramos unir las tablas hay que tener el mismo el formato de la otra tabla Divvy_Trips_2020_Q1, que tiene si columna ride_id en formato texto.
Usamos la funcion str() para ver su estructura
## spc_tbl_ [365,069 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ trip_id : chr [1:365069] "21742443" "21742444" "21742445" "21742446" ...
## $ start_time : POSIXct[1:365069], format: "2019-01-01 00:04:37" "2019-01-01 00:08:13" ...
## $ end_time : POSIXct[1:365069], format: "2019-01-01 00:11:07" "2019-01-01 00:15:34" ...
## $ bikeid : num [1:365069] 2167 4386 1524 252 1170 ...
## $ tripduration : num [1:365069] 390 441 829 1783 364 ...
## $ from_station_id : num [1:365069] 199 44 15 123 173 98 98 211 150 268 ...
## $ from_station_name: chr [1:365069] "Wabash Ave & Grand Ave" "State St & Randolph St" "Racine Ave & 18th St" "California Ave & Milwaukee Ave" ...
## $ to_station_id : num [1:365069] 84 624 644 176 35 49 49 142 148 141 ...
## $ to_station_name : chr [1:365069] "Milwaukee Ave & Grand Ave" "Dearborn St & Van Buren St (*)" "Western Ave & Fillmore St (*)" "Clark St & Elm St" ...
## $ usertype : chr [1:365069] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ gender : chr [1:365069] "Male" "Female" "Female" "Male" ...
## $ birthyear : num [1:365069] 1989 1990 1994 1993 1994 ...
## $ ride_length : 'difftime' num [1:365069] 390 441 829 1783 ...
## ..- attr(*, "units")= chr "mins"
## $ week_day : chr [1:365069] "martes" "martes" "martes" "martes" ...
## $ num_week_day : num [1:365069] 3 3 3 3 3 3 3 3 3 3 ...
## $ edad_cliente : num [1:365069] 36 35 31 32 31 42 41 35 30 29 ...
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Tambien realizamos funcion summary() para ver algunas medidas descriptivas
## trip_id start_time end_time
## Length:365069 Min. :2019-01-01 00:04:37 Min. :2019-01-01 00:11:07
## Class :character 1st Qu.:2019-01-23 05:26:54 1st Qu.:2019-01-23 05:49:40
## Mode :character Median :2019-02-25 07:52:56 Median :2019-02-25 08:03:50
## Mean :2019-02-19 21:43:15 Mean :2019-02-19 22:00:11
## 3rd Qu.:2019-03-17 16:52:47 3rd Qu.:2019-03-17 17:16:16
## Max. :2019-03-31 23:53:48 Max. :2019-06-17 16:04:35
##
## bikeid tripduration from_station_id from_station_name
## Min. : 1 Min. : 61 Min. : 2.0 Length:365069
## 1st Qu.:1777 1st Qu.: 326 1st Qu.: 76.0 Class :character
## Median :3489 Median : 524 Median :170.0 Mode :character
## Mean :3429 Mean : 1016 Mean :198.1
## 3rd Qu.:5157 3rd Qu.: 866 3rd Qu.:287.0
## Max. :6471 Max. :10628400 Max. :665.0
##
## to_station_id to_station_name usertype gender
## Min. : 2.0 Length:365069 Length:365069 Length:365069
## 1st Qu.: 76.0 Class :character Class :character Class :character
## Median :168.0 Mode :character Mode :character Mode :character
## Mean :198.6
## 3rd Qu.:287.0
## Max. :665.0
##
## birthyear ride_length week_day num_week_day
## Min. :1900 Min. : 61 mins Length:365069 Min. :1.000
## 1st Qu.:1975 1st Qu.: 326 mins Class :character 1st Qu.:3.000
## Median :1985 Median : 524 mins Mode :character Median :4.000
## Mean :1982 Mean : 1016 mins Mean :4.145
## 3rd Qu.:1990 3rd Qu.: 866 mins 3rd Qu.:6.000
## Max. :2003 Max. :10632022 mins Max. :7.000
## NA's :18023
## edad_cliente
## Min. : 22.00
## 1st Qu.: 35.00
## Median : 40.00
## Mean : 43.33
## 3rd Qu.: 50.00
## Max. :125.00
## NA's :18023
De la tabla Divvy_Trips_2019_Q1 la columna start_time creando un sumario de nombre Desc_Est_2019_Q1_StT
Desc_Est_2019_Q1_StT <- Divvy_Trips_2019_Q1 %>%
summarise(
mean_start_time = mean(Divvy_Trips_2019_Q1$start_time, na.rm = TRUE ),
media_start_time = median(Divvy_Trips_2019_Q1$start_time, na.rm = TRUE ),
desvst_start_time = round(sd(Divvy_Trips_2019_Q1$start_time, na.rm = TRUE ), digits = 2),
min_start_time = min(Divvy_Trips_2019_Q1$start_time, na.rm = TRUE ),
max_start_time = max(Divvy_Trips_2019_Q1$start_time, na.rm = TRUE ))De la tabla Divvy_Trips_2019_Q1 la columna biked_id creando un sumario de nombre Desc_Est_2019_Q1_Bkid
Desc_Est_2019_Q1_Bkid <- Divvy_Trips_2019_Q1 %>%
summarise(
mean_bikeid = mean(Divvy_Trips_2019_Q1$bikeid, na.rm = TRUE ),
media_bikeid = median(Divvy_Trips_2019_Q1$bikeid, na.rm = TRUE ),
min_bikeid = min(Divvy_Trips_2019_Q1$bikeid, na.rm = TRUE ),
max_bikeid = max(Divvy_Trips_2019_Q1$bikeid, na.rm = TRUE ),)De la tabla Divvy_Trips_2019_Q1 la columna tripduration creando un sumario de nombre Desc_Est_2019_Q1_Tripd
Desc_Est_2019_Q1_Tripd <- Divvy_Trips_2019_Q1 %>%
summarise(
mean_Tripd = mean(Divvy_Trips_2019_Q1$tripduration, na.rm = TRUE ),
media_Tripd = median(Divvy_Trips_2019_Q1$tripduration, na.rm = TRUE ),
min_Tripd = min(Divvy_Trips_2019_Q1$tripduration, na.rm = TRUE ),
max_Tripd = max(Divvy_Trips_2019_Q1$tripduration, na.rm = TRUE ),)De la tabla Divvy_Trips_2019_Q1 la columna from_station_id creando un sumario de nombre Desc_Est_2019_Q1_FrStId
Desc_Est_2019_Q1_Tripd <- Divvy_Trips_2019_Q1 %>%
summarise(
mean_FrStId = mean(Divvy_Trips_2019_Q1$from_station_id, na.rm = TRUE ),
media_FrStId = median(Divvy_Trips_2019_Q1$from_station_id, na.rm = TRUE ),
min_FrStId = min(Divvy_Trips_2019_Q1$from_station_id, na.rm = TRUE ),
max_FrStId = max(Divvy_Trips_2019_Q1$from_station_id, na.rm = TRUE ),)De la tabla Divvy_Trips_2019_Q1 la columna “usertype” creando el conteo de porque es tipo texto pondremos de nombre Count_2019_UserT en ella se omite los datos N.A con la funcion na.omit()
Posterior verificamos el resultado de Count_2019_UserT, en el nos proposrciona que de la columna “usertype” tenemos las cantidades de “Customer” = 23163 y de “Subscriber” = 341906 estos son valores absolutos
## tibble [2 × 2] (S3: tbl_df/tbl/data.frame)
## $ usertype: chr [1:2] "Customer" "Subscriber"
## $ n : int [1:2] 5934 339423
## - attr(*, "na.action")= 'omit' Named int [1:19712] 20 22 49 53 54 55 56 59 78 79 ...
## ..- attr(*, "names")= chr [1:19712] "20" "22" "49" "53" ...
Visualiza
De la tabla Divvy_Trips_2019_Q1 la columna “gender” creando el conteo de porque es tipo texto pondremos de nombre Count_2019_Gender al mismo tiempo, se omite los valos N.A con la funcion na.omit()
Posterior verificamos el resultado de Count_2019_Gender, en el nos proposrciona que de la columna “gender” tenemos las cantidades de “Female” = 66918 y de “Male” = 278440 estos son valores absolutos
## tibble [2 × 2] (S3: tbl_df/tbl/data.frame)
## $ gender: chr [1:2] "Female" "Male"
## $ n : int [1:2] 66918 278439
## - attr(*, "na.action")= 'omit' Named int [1:19712] 20 22 49 53 54 55 56 59 78 79 ...
## ..- attr(*, "names")= chr [1:19712] "20" "22" "49" "53" ...
Visual
De la tabla Divvy_Trips_2019_Q1 la columna “edad_cliente” crea conteo de porque es tipo texto pondremos de nombre Count_2019_Edad
Posterior verificamos el resultado de Count_2019_Edad, nos proporciona que de la columna “edad_cliente” tenemos las cantidades de en este caso no mostramos por ser extenso el volumen de datos pero posteior en area de graficos se incluira un histograma
## tibble [72 × 2] (S3: tbl_df/tbl/data.frame)
## $ edad_cliente: num [1:72] 22 23 24 25 26 27 28 29 30 31 ...
## $ n : int [1:72] 2 79 118 820 1888 1668 1868 5296 8544 11432 ...
## - attr(*, "na.action")= 'omit' Named int [1:19712] 20 22 49 53 54 55 56 59 78 79 ...
## ..- attr(*, "names")= chr [1:19712] "20" "22" "49" "53" ...
Visual
De la tabla Divvy_Trips_2019_Q1 la columna “week_day” crea conteo de porque es tipo texto pondremos de nombre Count_2019_WDay
Ordenamos en forma descente con la funccion arrange(desc())
Posterior verificamos el resultado de Count_2019_WDay, nos proposrciona que de la columna “week_day” tenemos las cantidades de “domingo” = 27999 ; “lunes” = 50399; “mates” = 61005; “miercoles” = 60414; “jueves”= 66903; “viernes” = 63047; “sabado”= 35302 Nos indica que entre semana hay mas uso siendo el dia jueves el mas alto
## spc_tbl_ [7 × 2] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ week_day: chr [1:7] "jueves" "viernes" "martes" "miércoles" ...
## $ n : int [1:7] 66903 63047 61005 60414 50399 35302 27999
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Visual
Se realizara el uso de filtros de varias columnas relevantes, para obtener informacion epecifica recordamos que es las columnas son tipo character es decir texto es importante recordar.
Iniciaremos el filtrado de usertype “Customer” De la tabla Divvy_Trips_2019_Q1 la columna usertype generamos un filtro de tipo de cliente “Customer” para ello lo guardaremos con nombre filt_2019_UserT_C usamos la funcion filter(), usamos == para que sea exacto
Ahora contamos el numero de “Customer de filt_2019_UserT_C con la funcion count()
De la tabla Divvy_Trips_2019_Q1 la columna usertype generamos un filtro de tipo de cliente “Subscriber” para ello lo guardaremos con nombre filt_2019_UserT_S usamos la funcion filter(), usamos == para que sea exacto
Contamos el numero de “Customer de filt_2019_UserT_S con la funcion count()
Se filtrara la tabla Divvy_Trips_2019_Q1 las columnas usertype solo “Customer” y gender se usa para indicarle una lista de valores usamos %in% y lista de vectores c(“Male”,“Female”), podemos visualizar la tabla, nos refleja que de usuarios “Customer” hay 5935 entre “Male” y “Female”.
filt_user_gend <- Divvy_Trips_2019_Q1 %>%
filter(usertype == "Customer" & gender %in% c("Male","Female"))Realizando una seleccionamos solo las columnas usertype y “gender”, de eses columnas, se filtra el tipo de cliente “Customer” y de la columana “gender” ambos generos “Females y Male” “Customer”, ademasy gender. De esta manera realizamos en una sola sentencia la seleccion y filtrado generando una subtabla llamada sel_user_gend_C
sel_user_gend_C <- Divvy_Trips_2019_Q1 %>%
select ("usertype", "gender") %>%
filter (usertype == "Customer" & gender %in% c("Male","Female")) Con estas eleccion podemos filtrar por genero de los clientes “Customer”. ahora seleccionamos el genero “Female”, esto lo ubicaremos en una tabla llamada Filt_user_gend_C_F, usando la subtabla sel_user_gend_C, nos indica los Clientes “Customer” “Female” son 1875
Filt_user_gend_C_F <- sel_user_gend_C %>%
select ("usertype", "gender") %>%
filter (usertype == "Customer" & gender=="Female") Conteo
Se hara lo mismo pero para “Male” con las mismas columnas pondremos de nombre a la subtabla Filt_user_gend_C_M
Filt_user_gend_C_M <- sel_user_gend_C %>%
select ("usertype", "gender") %>%
filter (usertype == "Customer" & gender=="Male")Podemos visualizar con la funcion count(), no entrega la cantidad de “Male” que es de 4060
De la misma manera que el anterior sentencia, vamos a crear y
seleccionar
columnas usertype y seleccionamos el cliente “Subscriber” y gender,
ambos generos, creamos una subtabla llamada sel_user_gend_S
sel_user_gend_S <- Divvy_Trips_2019_Q1 %>%
select ("usertype", "gender") %>%
filter (usertype == "Subscriber" & gender %in% c("Male","Female"))Filtramos el tipo de clientre “Subscriber”, por el genero “Female”, generamos una subtabla llamada Filt_user_gend_S_F usando la tabla sel_user_gend_S
Filt_user_gend_S_F <- sel_user_gend_S %>%
select ("usertype", "gender") %>%
filter (usertype == "Subscriber" & gender=="Female")Podemos visualizar con la funcion count(), entrega la cantidad de “Female” que es de 65043
De igual manera haresmo un filtro para clients “Male” crenado la
subtabla
Filt_user_gend_S_M utilizando la subtabla sel_user_gend_S
Filt_user_gend_S_M <- sel_user_gend_S %>%
select ("usertype", "gender") %>%
filter (usertype == "Subscriber" & gender=="Male")Podemos visualizar con la funcion count(), entrega la cantidad de “Male” que es de 274380
A continuacion realizamos una seleccion de dos columnas la misma que la denominaremos sel_user_durt
Usamos la tabla sel_user_durt para filtrar proporcionar otro filtro entre columnas usertype solo “Customer” y tripduration con una condicion que sea mayor o igual a 1 pondremos de nombre al filtro filt_user_durt_C
Generar una tabla summario que se guardara en TabS_User_Durt_C
Visual
Uso de group_by() y summarise() para guardar el promedio mean() de filt_user_durt_C lo guardamos en Grby_filt_user_durt_C
Grby_filt_user_durt_C <- filt_user_durt_C %>%
group_by(usertype) %>%
summarise(mean = mean (tripduration))Imprimir
## # A tibble: 1 × 2
## usertype mean
## <chr> <dbl>
## 1 Customer 3716.
La tabla sel_user_durt para filtrar prporcionar otro filtro entre columnas usertype solo “Subscriber” y tripduration con una condicion que sea mayor o igual a 1 pondremos de nombre al filtro filt_user_durt_S
Generamos tabla summario con la funcion summary() de TabS_User_Durt_S
Visual
Lo mismo realizamos usando group_by() y summarise() para guardar el promedio mean() filt_user_durt_S se guarda en Grby_filt_user_durt_S
Grby_filt_user_durt_S <- filt_user_durt_S %>%
group_by(usertype) %>%
summarise(mean = mean (tripduration))Imprimir
## # A tibble: 1 × 2
## usertype mean
## <chr> <dbl>
## 1 Subscriber 833.
Vemos que el promedio general en tripduration 473.2, mientras que filtrado por usertype cliente “Subscriber” tiene un tripduration 469, en cambio los usuarios “Customer” 617, son datos relevantes para el analisis.
Ahora seleccionaremos con la funcion select usertype y ride_length, para ello crearemos tabla llamada Sel_User_RidL
## usertype ride_length
## Length:365069 Min. : 61 mins
## Class :character 1st Qu.: 326 mins
## Mode :character Median : 524 mins
## Mean : 1016 mins
## 3rd Qu.: 866 mins
## Max. :10632022 mins
Se realiza el filtrado de la tabla Sel_User_RidL de columnas usertype los “Customer” junto con la columna “ride_length” indicando que es mayor a cero Nota. los datos que se visualizan son en segundos no en minutos
Realizamos un resumen sumario con la funcion summary() de Filt_Sel_User_RidL_C con el motivo de mirar algunas medidas Nota. los datos que se visualizan son en segundos no en minutos
## usertype ride_length
## Length:23163 Min. : 61 mins
## Class :character 1st Qu.: 809 mins
## Mode :character Median : 1401 mins
## Mean : 3717 mins
## 3rd Qu.: 2311 mins
## Max. :10632022 mins
Se genera un group_by del promedio de Filt_Sel_User_RidL_C con la
intencion de comparar con otros resusltados posterioes
Nota. los datos que se visualizan son en segundos no en minutos
Grby_Filt_Sel_User_RidL_C <- Filt_Sel_User_RidL_C %>%
group_by(usertype) %>%
summarise(mean = mean (ride_length))Se realiza el filtrado de la tabla Sel_User_RidL de columnas usertype los “Subscriber” junto con la columna “ride_length” indicando que es mayor a cero Pondremos de nombre al filtro Filt_Sel_User_RidL_s Nota. los datos que se visualizan son en segundos no en minutos
Realizamos un resumen sumario con la funcion summary() de Filt_Sel_User_RidL_S con el motivo de mirar algunas medidas Nota. los datos que se visualizan son en segundos no en minutos
## usertype ride_length
## Length:341906 Min. : 61.0 mins
## Class :character 1st Qu.: 317.0 mins
## Mode :character Median : 501.0 mins
## Mean : 833.6 mins
## 3rd Qu.: 802.0 mins
## Max. :6096428.0 mins
Genreraremos un group_by del promedio de Filt_Sel_User_RidL_S con la
intencion de comparar con otrso resusltados posterioes
Nota. los datos que se visualizan son en segundos no en minutos
Antes de realizar cualquier grafico generamos la tabla denominada
Count_Sel_User_RidL_U Cuenta la tabla y se conforma por porcentaje
unicamente clientes la columna “usertype” # de la tabla
Sel_User_RidL.
En este caso se utiliza la tabla con formula “percent = n/sum(n)*100”,
porque “no” es un argumento numerico.
Count_Sel_User_RidL_U <- Sel_User_RidL %>%
count(usertype) %>%
mutate (percent = n/sum(n)*100) # argumento no numericoSe genera otra tabla denominada Count_Sel_User_RidL_R ,en porcentaje unicamente tiempo de uso de las bicicletas de la columna “ride_length” usando tabla Sel_User_RidL, en esta tabla el porcentaje atravez pero nos da en toda la tabla su promedio general. La funcion mutate() nos permite calcular el promedio mean(), esta tabla es solo informativa.
Count_Sel_User_RidL_R <- Sel_User_RidL %>%
count(ride_length) %>%
mutate(mean_percent=mean(ride_length)) # argumento numericoAsi mismo gerera una tabla no relevante pero informativa de las columnas usertype y ride_lenght juntas denominada Count_Sel_User_RidL_UR. Genera el calculo a traves de la funcion mutate(), obteniendo el promedio mean() de la columna ride_length, de la tabla Sel_User_RidL
Count_Sel_User_RidL_UR <- Sel_User_RidL %>%
count(usertype, ride_length) %>%
mutate( mean_percent=mean(ride_length)) # argumento numericoGeneramos tres sumarios de Count_Sel_User_RidL_U, Count_Sel_User_RidL_R y Count_Sel_User_RidL_UR y vemos su estructura str()
## usertype n percent
## Length:2 Min. : 23163 Min. : 6.345
## Class :character 1st Qu.:102849 1st Qu.:28.172
## Mode :character Median :182535 Median :50.000
## Mean :182535 Mean :50.000
## 3rd Qu.:262220 3rd Qu.:71.828
## Max. :341906 Max. :93.655
Sumario
## ride_length n mean_percent
## Min. : 61 mins Min. : 1.00 Min. :19281 mins
## 1st Qu.: 1728 mins 1st Qu.: 1.00 1st Qu.:19281 mins
## Median : 3430 mins Median : 3.00 Median :19281 mins
## Mean : 19281 mins Mean : 54.76 Mean :19281 mins
## 3rd Qu.: 6262 mins 3rd Qu.: 33.00 3rd Qu.:19281 mins
## Max. :10632022 mins Max. :586.00 Max. :19281 mins
Sumario
## usertype ride_length n
## Length:10066 Min. : 61 mins Min. : 1.00
## Class :character 1st Qu.: 1343 mins 1st Qu.: 1.00
## Mode :character Median : 2612 mins Median : 3.00
## Mean : 13441 mins Mean : 36.27
## 3rd Qu.: 4691 mins 3rd Qu.: 11.00
## Max. :10632022 mins Max. :573.00
## mean_percent
## Min. :13441 mins
## 1st Qu.:13441 mins
## Median :13441 mins
## Mean :13441 mins
## 3rd Qu.:13441 mins
## Max. :13441 mins
Sumario
## usertype ride_length
## Length:365069 Min. : 61 mins
## Class :character 1st Qu.: 326 mins
## Mode :character Median : 524 mins
## Mean : 1016 mins
## 3rd Qu.: 866 mins
## Max. :10632022 mins
Estructura
## tibble [2 × 3] (S3: tbl_df/tbl/data.frame)
## $ usertype: chr [1:2] "Customer" "Subscriber"
## $ n : int [1:2] 23163 341906
## $ percent : num [1:2] 6.34 93.66
Estructura
## tibble [6,667 × 3] (S3: tbl_df/tbl/data.frame)
## $ ride_length : 'difftime' num [1:6667] 61 62 63 64 ...
## ..- attr(*, "units")= chr "mins"
## $ n : int [1:6667] 30 24 27 25 26 28 25 33 22 16 ...
## $ mean_percent: 'difftime' num [1:6667] 19280.5087745613 19280.5087745613 19280.5087745613 19280.5087745613 ...
## ..- attr(*, "units")= chr "mins"
Estructura
## tibble [10,066 × 4] (S3: tbl_df/tbl/data.frame)
## $ usertype : chr [1:10066] "Customer" "Customer" "Customer" "Customer" ...
## $ ride_length : 'difftime' num [1:10066] 61 63 64 67 ...
## ..- attr(*, "units")= chr "mins"
## $ n : int [1:10066] 4 1 1 1 1 1 1 1 3 2 ...
## $ mean_percent: 'difftime' num [1:10066] 13441.1175243394 13441.1175243394 13441.1175243394 13441.1175243394 ...
## ..- attr(*, "units")= chr "mins"
Se creara graficos en este caso de informacion relevante para el analisis no basamos en ciertas normativa que los expertos aplican para graficos, los mismos que tendran todos los graficos , como indica los expertos podremos una nomenclatura para los graficos en este caso la letra P y numero en el primer grafico le designaremos P1 asi consecutivamente cada grafico.
Esta es una formula permite graficar el numero por tipo de cliente y su porcentaje de la tabla Count_Sel_User_RidL_U la columna usertype, se usa geom_col, porque con ella se puede contar cada cliente indvidual y tambien su porcentaje individual por cada cliente, la funcion “paste0”, se refiere a concatenar multiples cadenas de texto en una solo, sin uso de separadores (sin espacios) de texto para concatenar, mientra que la funcion”vjust()” se usa para que las etiquetas quede encima de las barras.
Adicionalmente usaremos la funsion colors(), nos muestra listado de colores, todo grafico se usara, en su mayoria dos tonalidades skyblue1 y lightblue
P1 <- ggplot(data=Count_Sel_User_RidL_U, aes(x=usertype, y=n, fill= usertype))+
geom_col()+
geom_text(aes(label=paste0(n, " (", round(percent,1),"%)")), vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title= "Tipo de Cliente por\nCantidad y su Porcentaje 2019",
x="Clientes", y="Cantidad",
caption = "Data: Empresa Motivate International Inc\nP1")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none") label=paste0. Se usa para concatenar, usando una cadena de caracteres
vacios como separador.
Utilizamos vjust=-0.5, para poner las etiqueta encima de las barras
scale_fill_manual.Cambia los colores de relleno manualmente ya
expuestos
En la sentencia anterior centramos el titulo con la funcion hjust()
Visual
El grafico P1 nos da la visualizacion del Tipo de Cliente y su Porcentaje, en el nos muestra que “Subscriber” tiene 341906 con un 93.7%, mientras clientes “Customer” tiene 23163 con el 6.34%.
Generamos una tabla del promedio con la tabla “Sel_User_RidL” del tiempo recorrido por tipo de cliente. Se denominara Main_Count_Sel_User_RidL_UR, en ella agruparemos con funcion group_by() por tipo de usuario y resumido por la funcion summarise () en la que la columna ride_length la convierte en numerico con la funcion as.numeric() y podremos calcular con la funcion mutate() y el promedio con la funcion mean() Usamos esta tabla simplemente porque, es similar la la tabla “sel_user_durt”, solo con proposito practico.
Promedio
Main_Count_Sel_User_RidL_UR <- Sel_User_RidL %>%
group_by(usertype) %>%
summarise(
Mean_Rd_Length = as.numeric(mean(ride_length, na.rm = TRUE)))%>%
mutate( percent = Mean_Rd_Length / sum(Mean_Rd_Length)*100 )La Tabla muestra el resultado es que la trayectoria que recorren clientes “Customer” es de 222990.94, siendo un 81.7% mientras que los los clientes “Subscribes” es de 50014.33, siendo el 18.3% de tiempo recorrido por tipo de cliente, generamos un grafico para visualizar los datos, el que denominaremos P2
P2 <- ggplot(data=Main_Count_Sel_User_RidL_UR, aes(x = usertype,
y = Mean_Rd_Length, fill = usertype)) +
geom_col() +
geom_text(aes(label=paste0(round(Mean_Rd_Length,1), " (",round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title = "Tipo de Cliente por Tiempo\nRecorrido y su Promedio en % 2019",
x= "Clientes", y = "Promedio del Tiempo Recorrido",
caption = "Data: Empresa Motivate International Inc\nP2")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")nota.- scale_fill_manual para asignación manual de colores
Visualizacion
Mostraremos como una especie de resumen pero con graficos paralelos P1 y P2 esta manera se puede comparar las graficas
(P1 + P2)+
plot_annotation(
title="Distribucion por TIPO DE CLIENTE",
theme=theme(plot.title = element_text(hjust = 0.5)))Si bien podemos visualizar la cantidades de “Customer” es inferior a “Subscriber”, no da indicios que las campañas de marketing para subscribirse, han tenido un gran exito como podemos ver en la visualizacion y un parte de proponer una nueva campaña de marketing, se sotiene por el tiempo promedio recorrido de “Customer” superior al de “Subscriber”, demustra la gran acogida, que tiene las bicicletas compartidas.
Seleccionamos tabla Count_2019_WDay que contiene los datos, pero al ver su estructura de la columna week_day es character y se cambiara a factor, permite que se pueda manipular los datos.
Ahora se realizara la creacion de una nueva columna en tabla Count_2019_WDay, para obtener el porcentaje en una columna nueva llamada “percent”.
P3 <- ggplot(data = Count_2019_WDay , aes(x=week_day, y=n, fill = n ))+
geom_bar (stat = "identity")+
geom_text(aes(label=paste0(round(n,1), "\n (",round(percent,1),"%)"))
# "\n Es el salto de linea
, vjust = -0.3 , size = 4 )+
expand_limits(y = max(Count_2019_WDay$n) * 1.15) +
labs(title = "Uso de Bicicletas por Dia de la Semana 2019",
x= "Dia de la Semana", y = "Tiempo Recorrido por Dia ",
caption = "Data: Empresa Motivate International Inc\nP3")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")nota.- expand_limits:funcion que amplia un eje (x o y) sin cambiar datos (etiquetas)
Visualizacion
Tanto en la tabla Count_2019_WDay, como en el grafico nos muestra, que el dia de mayor uso es el dia jueves con 66903 corresponde 18.3%, notamos los dias de mayor uso, son dias entre semana, lo que muestra que los clientes usan para labores cotidianas y en menor escala los fines de semana.
Seleccion de variables usertype y from_station_id 2019, para crear grafico
P4<- ggplot(data = Sel_User_Station,aes(x=from_station_id, fill = usertype ) )+
geom_histogram(aes(y=after_stat(density)), binwidth = 5, position="dodge",
color = "blue", alpha=0.6)+
geom_density(aes( color = usertype, linewidth = 1)) +
facet_wrap(~ usertype , nrow = 1)+
labs( title = "Estaciones por Usuarios 2019",x = "Estaciones",y = "Densidad",
caption = "Data: Empresa Motivate International Inc\nP4") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Visual
EStructura
## tibble [72 × 2] (S3: tbl_df/tbl/data.frame)
## $ edad_cliente: num [1:72] 22 23 24 25 26 27 28 29 30 31 ...
## $ n : int [1:72] 2 79 118 820 1888 1668 1868 5296 8544 11432 ...
## - attr(*, "na.action")= 'omit' Named int [1:19712] 20 22 49 53 54 55 56 59 78 79 ...
## ..- attr(*, "names")= chr [1:19712] "20" "22" "49" "53" ...
Calculo del promedio de Edad 2019
Rangos por Edad 2019
Rang_Edad_2019 <- Count_2019_Edad %>%
mutate(
Edad_Rang=case_when(edad_cliente>20 & edad_cliente<=40 ~1,
edad_cliente>=41 &edad_cliente<=60 ~2,
edad_cliente>=61~3))Con el rango establecido Rang_Edad_2019, juntaremos con a la tabla Count_2019_Edad,con la funcion cbind(), que agrega una columna a una tabla de datos, que tenga coincidencia con el mismo numero de filas de la tabla existente.Pero pondremos un nombre diferente que loa guardaremos como Rang_Edad_2019.
Ahora sacaremos el porcentaje de cada rango de la tabla Rang_Edad_2019
Rang_Edad_2019<- Rang_Edad_2019 %>%
group_by (Edad_Rang) %>%
summarise(n= sum(n)) %>%
mutate(percent= round(n/ sum(n)*100,2))Estructura
## tibble [3 × 3] (S3: tbl_df/tbl/data.frame)
## $ Edad_Rang: num [1:3] 1 2 3
## $ n : int [1:3] 177336 131685 36336
## $ percent : num [1:3] 51.4 38.1 10.5
Visual
P5 <- ggplot(data=Rang_Edad_2019, aes(x=Edad_Rang,y=n, fill = Edad_Rang))+
geom_col(stat = "identity", position = "dodge")+
geom_text(aes(label=paste0(n, " (", round(percent,1),"%)"))
, vjust = -0.5)+
scale_x_continuous(breaks = c(1,2,3),
labels = c("20 a 40","41 a 60","61 a +" ))+
labs(title = "Rango por Edades 2019",
x= "Rangos por Edades ", y = "Cantidad de Edades por Rangos 2019",
caption = "Data: Empresa Motivate International Inc\nP5")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Visual
nota.-scale_x_continuous: Se usa cuando el rango es numerico, cambia las etiquetas nota.- del eje x por textos, crea vectores llamados breaks() y labels().
(P4 + P5)+
plot_annotation(
title="Distribucion por Edades",
theme=theme(plot.title = element_text(hjust = 0.5,size=14)))Seleccion de variables en vector
Omision de N.A en Sel_User_Gndr_Edad
Promedio de edad de Sel_User_Gndr_Edad
P6 <- ggplot(data = Sel_User_Gndr_Edad,aes(x=edad_cliente) )+
geom_histogram(aes(y= after_stat(density)),
binwidth = 5,
fill = "skyblue",
color = "black",
alpha = 0.6) +
geom_density(color = "blue", linewidth = 1) +
geom_vline(aes(xintercept = mean(edad_cliente)),
color="blue", linetype="dashed", size=1)+
annotate("text",x=Mean_Edad,y = Inf,
label = paste(" ", round(Mean_Edad, 1)),
vjust = 1.5,
color = "blue",
size = 4 ) +
labs( title = "Densidad de la Edad de Clientes\ny Promedio General de Edad2019",
x = "Edad", y = "Densidad de Edad",
caption = "Data: Empresa Motivate International Inc\nP6")+
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5))## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Visual
Seleccion de variables dentro de vectores
Omision de N.A en Sel_User_Gen_Station
P7 <- ggplot(data= Sel_User_Gen_Station,
aes(x = from_station_id, fill = usertype)) +
geom_histogram( aes(y = after_stat(density)),
binwidth = 5,
position = "dodge",
alpha = 0.6 ) +
geom_density( aes(color = gender), linewidth = 1 ) +
facet_wrap(~ usertype, nrow = 1) +
labs( title = "Estaciones por\nTipo Cliente y Genero 2019",
x = "Estaciones",
y = "Densidad",
caption = "Data: Empresa Motivate International Inc\nP7" ) +
theme_minimal() +
theme( plot.title = element_text(hjust = 0.5) )Visual
(P4 + P7)+
plot_annotation(
title="Distribucion por Estaciones por\nTipo de Cliente y Genero",
theme=theme(plot.title = element_text(hjust = 0.5,size=14)))P8<- ggplot(data = Sel_User_Gndr_Edad,aes(x=edad_cliente, fill = gender) )+
geom_histogram(aes(y=after_stat(density)), binwidth = 5, position="dodge",
fill="skyblue", color = "blue", alpha=0.1)+
geom_density( color = "lightblue", linewidth = 1) +
facet_wrap(~ gender, nrow = 1)+
geom_vline(aes(xintercept = mean(edad_cliente)),
color="blue", linetype="dashed", size=1)+
annotate("text",x=Mean_Edad,y = Inf,
label = paste(" ", round(Mean_Edad, 1)),
vjust = 1.5,
color = "blue",
size = 4 ) +
labs( title = "Densidad de Edades por Genero 2019",x = "Edad",y = "Densidad",
caption = "Data: Empresa Motivate International Inc\nP8") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Visual
Visual
(P6 + P8)+
plot_annotation(
title="Distribucion por Edades",
theme=theme(plot.title = element_text(hjust = 0.5,size=14)))P9 <- ggplot(data = Sel_User_Gndr_Edad, aes(x = usertype,
y = edad_cliente, fill = gender)) +
geom_boxplot(alpha = 0.7, outlier.alpha = 0.4) +
geom_text(data = Media_Edad, aes(x = usertype, y = media_edad,
label = paste0("Edad\nMedia: ", round(media_edad, 1))),
vjust=-0.5, color="blue", size=4)+
facet_wrap(~ gender) +
scale_fill_manual(values = c("Male" = "skyblue", "Female" = "pink" ))+
labs( title = "Distribucion de la Edad por\nTipo de Cliente y Genero 2019",
x = "Tipo de Cliente", y = "Edad",
caption = "Data: Empresa Motivate International Inc\nP9" ) +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5), legend.position = "none" )(P8 + P9)+
plot_annotation(
title="Densidades y Distribucion por\nTipo de Cliente, Edades, Genero 2019",
theme=theme(plot.title = element_text(hjust = 0.5,size=14)))En este apartado existira menor consultas por motivos de la misma tabla Divvy_Trips_2020_Q1 que no tiene el mismo contenido que la anteior.
Ahora seleccionaremos las variables member_casual y ride_length, para ello crearemos tabla llamada Sel_User_RidL_2020
Calculo de porcentaje de variable member_casual de tabla Sel_User_RidL_2020
Count_Sel_User_RidL_2020 <- Sel_User_RidL_2020 %>%
count(member_casual ) %>%
mutate (percent = n/sum(n)*100) nota.-Argumento no numerico
P10 <- ggplot(data=Count_Sel_User_RidL_2020, aes(x=member_casual, y=n,
fill= member_casual))+
geom_col()+
geom_text(aes(label=paste0(n, " (", round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title= "Tipo de Cliente por\nCantidad y su Porcentaje 2020 ",
x="Clientes", y="Cantidad",
caption = "Data: Empresa Motivate International Inc\nP10")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Nota.-label=paste0. Se usa para concatenar, usando una cadena de caracteres vacios como separador. Nota.-Utilizamos vjust=-0.5, para poner las etiqueta encima de las barras Nota.-scale_fill_manual.Cambia los colores de relleno manualmente ya expuestos Nota.-En la sentencia anterior centramos el titulo con la funcion hjust()
Visualizamos
El grafico P10 nos da la visualizacion del Tipo de Cliente y su Porcentaje, en el nos muestra que “Members” tiene 341906 con un 93.7%, mientras clientes “Casual” tiene 23163 con el 6.34%.
Main_Count_Sel_User_RidL_2020 <- Sel_User_RidL_2020 %>%
group_by(member_casual) %>%
summarise(
Mean_Rd_Length = as.numeric(mean(ride_length, na.rm = TRUE)))%>%
mutate( percent = Mean_Rd_Length / sum(Mean_Rd_Length)*100 )La Tabla muestra el resultado es que la trayectoria que recorren clientes “Casual” es de 5746.9586, siendo un 88.31% mientras que los los clientes “Members” es de 760.6268, siendo el 11.68% de tiempo recorrido por tipo de cliente, generamos un grafico para visualizar los datos, el que denominaremos P11
P11 <- ggplot(data=Main_Count_Sel_User_RidL_2020, aes(x = member_casual,
y = Mean_Rd_Length, fill = member_casual)) +
geom_col() +
geom_text(aes(label=paste0(round(Mean_Rd_Length,1), " (",round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
# scale_fill_manual para asignación manual de colores
labs(title = "Tipo de Cliente por Tiempo\nRecorrido y su Promedio en % 2020",
x= "Clientes", y = "Promedio del Tiempo Recorrido",
caption = "Data: Empresa Motivate International Inc\nP11")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Mostraremos como una especie de resumen pero con graficos paralelos P10 y P11 esta manera se puede comparar las graficas
(P10 + P11)+
plot_annotation(
title="Distribucion por Tipo de Cliente 2020",
theme=theme(plot.title = element_text(hjust = 0.5)))De la tabla Divvy_Trips_2020_Q1 la columna “week_day” crea conteo de porque es tipo texto pondremos de nombre Count_2019_WDay
Ordenamos en forma descente de la variable “n” con la funcion arrange(desc())
Posterior verificamos el resultado de Count_2020_WDay, nos proposrciona que de la columna “week_day” tenemos las cantidades de “domingo” = 50850 ; “lunes” = 66778; “mates” = 74961; “miercoles” = 69911; “jueves”= 66140; “viernes” = 60663; “sabado”= 37584 Nos indica que entre semana hay mas uso siendo el dia martes el mas alto
Estructura
## tibble [7 × 2] (S3: tbl_df/tbl/data.frame)
## $ week_day: chr [1:7] "martes" "miércoles" "lunes" "jueves" ...
## $ n : int [1:7] 74961 69911 66778 66140 60663 50850 37584
Visual
Seleccionamos tabla Count_2020_WDay que contiene los datos, pero al ver su estructura de la columna week_day es character y se cambiara a factor, permite que se pueda manipular los datos. levels es el argumento del constructor factor() que define qué categorías existen y en qué orden.
Ahora se realizara la creacion de una nueva columna en tabla Count_2019_WDay, para obtener porcentaje, una columna nueva llamada “percent”con dos decimales.
P12 <- ggplot(data = Count_2020_WDay , aes(x=week_day, y=n, fill = n ))+
geom_bar (stat = "identity")+
geom_text(aes(label=paste0(round(n,1), "\n (",round(percent,1),"%)"))
# "\n Es el salto de linea
, vjust = -0.3 , size = 4 )+
expand_limits(y = max(Count_2020_WDay$n) * 1.15) +
labs(title = "Uso de Bicicletas por Dia de la Semana 2020",
x= "Dia de la Semana", y = "Tiempo Recorrido por Dia ",
caption = "Data: Empresa Motivate International Inc\nP12")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Nota.-expand_limits:funcion que amplia un eje (x o y) sin cambiar datos (etiquetas)
Visual
Realizamos sumario de tabla Sel_User_Station_2020
## member_casual start_station_id
## Length:426887 Min. : 2.0
## Class :character 1st Qu.: 77.0
## Mode :character Median :176.0
## Mean :209.8
## 3rd Qu.:298.0
## Max. :675.0
P13<- ggplot(data = Sel_User_Station_2020,aes(x=start_station_id,
fill = member_casual ) )+
geom_histogram(aes(y=after_stat(density)), binwidth = 5, position="dodge",
color = "blue", alpha=0.6)+
geom_density(aes( color = member_casual, linewidth = 1)) +
facet_wrap(~ member_casual , nrow = 1)+
labs( title = "Estaciones por Usuarios 2020",x = "Estaciones",y = "Densidad",
caption = "Data: Empresa Motivate International Inc\nP13") +
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Visual
Para realizar join, es decir la union de tablas, lo principal es que las variables o columnas de las tablas 2019 y 2020 tenga tipo de formato igual de tal manera que al unir en este las tablas se asegure un adecuado join. para ello veremos su tipos de formato por medio de la funcion str(). se incluye un cambio de nombre a cada tabla de manera que que no altere lo hecho anteriormente. Divvy_Trips_2019_Q1 = Join_2019 y Divvy_Trips_2020_Q1 = Join_2020 se realizara un “left_join()” que permite mantener las filas de la primera tabla Join_2019 y coincidentes con la tabla Join_2020.
Visualizacion de estructura de tipos de formatos en las tablas
Estructura
## spc_tbl_ [365,069 × 16] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ trip_id : chr [1:365069] "21742443" "21742444" "21742445" "21742446" ...
## $ start_time : POSIXct[1:365069], format: "2019-01-01 00:04:37" "2019-01-01 00:08:13" ...
## $ end_time : POSIXct[1:365069], format: "2019-01-01 00:11:07" "2019-01-01 00:15:34" ...
## $ bikeid : num [1:365069] 2167 4386 1524 252 1170 ...
## $ tripduration : num [1:365069] 390 441 829 1783 364 ...
## $ from_station_id : num [1:365069] 199 44 15 123 173 98 98 211 150 268 ...
## $ from_station_name: chr [1:365069] "Wabash Ave & Grand Ave" "State St & Randolph St" "Racine Ave & 18th St" "California Ave & Milwaukee Ave" ...
## $ to_station_id : num [1:365069] 84 624 644 176 35 49 49 142 148 141 ...
## $ to_station_name : chr [1:365069] "Milwaukee Ave & Grand Ave" "Dearborn St & Van Buren St (*)" "Western Ave & Fillmore St (*)" "Clark St & Elm St" ...
## $ usertype : chr [1:365069] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ gender : chr [1:365069] "Male" "Female" "Female" "Male" ...
## $ birthyear : num [1:365069] 1989 1990 1994 1993 1994 ...
## $ ride_length : 'difftime' num [1:365069] 390 441 829 1783 ...
## ..- attr(*, "units")= chr "mins"
## $ week_day : chr [1:365069] "martes" "martes" "martes" "martes" ...
## $ num_week_day : num [1:365069] 3 3 3 3 3 3 3 3 3 3 ...
## $ edad_cliente : num [1:365069] 36 35 31 32 31 42 41 35 30 29 ...
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Estructura
## tibble [426,887 × 15] (S3: tbl_df/tbl/data.frame)
## $ ride_id : chr [1:426887] "EACB19130B0CDA4A" "8FED874C809DC021" "789F3C21E472CA96" "C9A388DAC6ABF313" ...
## $ started_at : POSIXct[1:426887], format: "2020-01-21 20:06:59" "2020-01-30 14:22:39" ...
## $ ended_at : POSIXct[1:426887], format: "2020-01-21 20:14:30" "2020-01-30 14:26:22" ...
## $ start_station_name: chr [1:426887] "Western Ave & Leland Ave" "Clark St & Montrose Ave" "Broadway & Belmont Ave" "Clark St & Randolph St" ...
## $ start_station_id : num [1:426887] 239 234 296 51 66 212 96 96 212 38 ...
## $ end_station_name : chr [1:426887] "Clark St & Leland Ave" "Southport Ave & Irving Park Rd" "Wilton Ave & Belmont Ave" "Fairbanks Ct & Grand Ave" ...
## $ end_station_id : num [1:426887] 326 318 117 24 212 96 212 212 96 100 ...
## $ start_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ start_lng : num [1:426887] -87.7 -87.7 -87.6 -87.6 -87.6 ...
## $ end_lat : num [1:426887] 42 42 41.9 41.9 41.9 ...
## $ end_lng : num [1:426887] -87.7 -87.7 -87.7 -87.6 -87.6 ...
## $ member_casual : chr [1:426887] "member" "member" "member" "member" ...
## $ ride_length : 'difftime' num [1:426887] 451 223 171 529 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : chr [1:426887] "martes" "jueves" "jueves" "lunes" ...
## $ num_week_day : num [1:426887] 3 5 5 2 5 6 6 6 6 6 ...
Creacion de tabla Join_2019
Creacion de tabla Join_2020
En la tabla Join_2020 se encuentra la varible “member_casual” su filas contiene , tipo de cliente como “member” y ” “casual”, se le va a cambiar por sinonimos por “Subscriber” y “Customer” respectivamente, por medio de las funciones mutate(member_casual) y funcion recode()
Me interesa ver cual es la diferencia entre años y que porcentaje se incremento para dicho efecto contamos el numero de filas de cada tabla,
Numero de filas
Numero de filas
Diferencia de cantidades entra años 2019 y 2020 lag(n_Fi) obtiene el valor de Numero de Filas del registro anterior, permitiendo la resta para obtener la diferencia.
Para poder graficar, habia que cambiar los “N.A” por cero “0”, con el fin de que al graficar muestre valor cero y porcentaje cero del 2019. En ella usamos condicional con la funcion ifelse(), cambia con la funcion is.na() para valores “N.A” por “0” y no elimina la fila completa.
P14 <- ggplot(data=Calc_Dif, aes(x=Years, y=n_Fi, fill= Years))+
geom_col()+
geom_text(aes(label=paste0(n_Fi," " ,Dif, " (", round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title= "Diferencia de Clietes por Year\nPorcentaje 2019 y 2020 ",
x="Years", y="Cantidad de Registros",
caption = "Data: Empresa Motivate International Inc\nP14")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Visual
En el grafico P14, se puede visualizar, el incremento entre los años 2019 y 2020, es de 61818 corresponde año 2020 un 16.9 % mas que en el 2019. Cantidades en 2019 muestra cero, porque no hay año que antecede.
La funcion left_join() es la que se utilizara, porque mantiene todas las variables de la tabla Join_2019 para unir con la tabla Join_2020 a lo largo, antes de hacerlo y por recomendacion de expertos, lo mejor es crenomnbrar las variables Join_2020 y alinearlas con Join_2019 de, una manera# que permitira que no exista errores a futuro.
Join_2020<- Join_2020 %>%
rename ( trip_id = ride_id , start_time = started_at,
end_time= ended_at,
usertype= member_casual,
from_station_id= start_station_id,
from_station_name = start_station_name,
to_station_id=end_station_id,
to_station_name= end_station_name)Ahora realizamos un left_join con el el fin de mantener todas las variables de join_2019 y las que coincidan con Join_2020, si es verdad muestra c_trip_id, se debe a que no coincide por tal motivo se muetra con N.A.
Visualiza
Efectivamente junta las tablas de manera horizontal, sin embargo para el analisis, tenemos que realizar otros pasos adicionales y es la de juntar las variable tanto de la tabla Join_2019 y Join_2020 similares, para que muestre de manera vertical. Realizaremos un ejemplo con un fin practico. uniremos verticalmente las variables start_time.x con start_time.y, en una variable llamada start_time, con la funcion unite, adicionalmente, que nos omita todos los na.rm y que no nos remueva otras variables. Pondremos como nombre a la tabla Union_Join_Total
Visualizar
Como podemos visualizar, no existe ninguna alteracion en la nueva columna y tampoco hay un aumento en la columna, debido que start_time.y en Join_Total no muestra datos.Por lo que se procedera con otra funcion llamada bind_rows() en lugar de left_join().
Ahora utilizaremos la funcion bind_rows(), para apilar verticalmente la informacion, para el analisis usaremos las tablas Join_2019 y Join_2020, para este efecto. Pondremos de nombre una nueva tabla Union_Total.
Ahora seleccionaremos las variables usertype y ride_length, para ello crearemos tabla llamada Sel_User_RidL_UTotal
Sumario
## usertype ride_length
## Length:791956 Min. : -552 secs
## Class :character 1st Qu.: 513 secs
## Mode :character Median : 1838 secs
## Mean : 28830 secs
## 3rd Qu.: 29220 secs
## Max. :637921320 secs
Realizamos su porcentaje de la tabla Sel_User_RidL_UTotal
Count_Sel_User_RidL_UTotal <- Sel_User_RidL_UTotal %>%
count(usertype ) %>%
mutate (percent = n/sum(n)*100)Nota.-Argumento no numerico
P15 <- ggplot(data=Count_Sel_User_RidL_UTotal, aes(x=usertype, y=n,
fill= usertype))+
geom_col()+
geom_text(aes(label=paste0(n, " (", round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title= "Tipo de Cliente por\nCantidad y su Porcentaje 2019 y 2020 ",
x="Clientes", y="Cantidad",
caption = "Data: Empresa Motivate International Inc\nP15")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Nota.-label=paste0. Se usa para concatenar, usando una cadena de
caracteres vacios como separador.
Nota.-Utilizamos vjust=-0.5, para poner las etiqueta encima de las
barras
Nota.-scale_fill_manual.Cambia los colores de relleno manualmente ya
expuestos
Nota.-En la sentencia anterior centramos el titulo con la funcion
hjust()
Visualizamos
El grafico P15 nos da la visualizacion de la tabla Count_Sel_User_RidL_UTotal del Tipo de Cliente y su Porcentaje, en el nos muestra que “Subscriber” tiene 720313 con un 91%, mientras clientes “Customer” tiene 71643 con el 9%.
Main_Count_Sel_User_RidL_UTotal <- Sel_User_RidL_UTotal %>%
group_by(usertype) %>%
summarise(
Mean_Rd_Length = as.numeric(mean(ride_length, na.rm = TRUE)))%>%
mutate( percent = Mean_Rd_Length / sum(Mean_Rd_Length)*100 )La Tabla muestra el resultado es que la trayectoria que recorren clientes “Customer” es de 222990.94, siendo un 81.7% mientras que los los clientes “Subscribes” es de 50014.33, siendo el 18.3% de tiempo recorrido por tipo de cliente, generamos un grafico para visualizar los datos, el que denominaremos P16
P16 <- ggplot(data=Main_Count_Sel_User_RidL_UTotal, aes(x = usertype,
y = Mean_Rd_Length, fill = usertype)) +
geom_col() + geom_text(aes(label=paste0(round(Mean_Rd_Length,1),
" (",round(percent,1),"%)"))
, vjust = -0.5)+
scale_fill_manual(values = c("skyblue1","lightblue"))+
labs(title = "Tipo de Cliente por Tiempo Recorrido y\nPromedio en % 2019 y2020",
x= "Clientes", y = "Promedio del Tiempo Recorrido",
caption = "Data: Empresa Motivate International Inc\nP16")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Nota.-# scale_fill_manual para asignacion manual de colores
Visual
Mostraremos como una especie de resumen con graficos paralelos P15 y P16 esta manera se puede comparar las graficas
(P15 + P16)+
plot_annotation(
title="DISTRIBUCION POR TIPO DE CLIENTE YEARS 2019 Y 2020",
theme=theme(plot.title = element_text(hjust = 0.5)))De la tabla Union_Total la columna “week_day” crea conteo de porque es tipo texto pondremos de nombre Count_Union_Total_WDay
Ordenamos en forma descente de la variable “n” con la funcion arrange(desc())
Posterior verificamos el resultado de Count_Union_Total_WDay, nos proposrciona que de la columna “week_day” tenemos las cantidades de “domingo” = 78849 ; “lunes” = 117177; “mates” = 135966; “miercoles” = 130325; “jueves”= 133043; “viernes” = 123710; “sabado”= 72886 Nos indica que entre semana hay mas uso siendo el dia martes el mas alto
Estructura
## spc_tbl_ [7 × 2] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ week_day: chr [1:7] "martes" "jueves" "miércoles" "viernes" ...
## $ n : int [1:7] 135966 133043 130325 123710 117177 78849 72886
## - attr(*, "spec")=
## .. cols(
## .. trip_id = col_double(),
## .. start_time = col_datetime(format = ""),
## .. end_time = col_datetime(format = ""),
## .. bikeid = col_double(),
## .. tripduration = col_number(),
## .. from_station_id = col_double(),
## .. from_station_name = col_character(),
## .. to_station_id = col_double(),
## .. to_station_name = col_character(),
## .. usertype = col_character(),
## .. gender = col_character(),
## .. birthyear = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
Visual
Seleccionamos tabla Count_Union_Total_WDay que contiene los datos, para ver su estructura de la columna week_day es character y se cambiara a factor, permite que se pueda manipular los datos. levels es el argumento del constructor factor() que define qué categorías existen y en qué orden.
Count_Union_Total_WDay$week_day<-factor( Count_Union_Total_WDay$week_day,
levels=Count_Union_Total_WDay$week_day)Ahora se realizara la creacion de una nueva columna en tabla Count_Union_Total_WDay, para obtener porcentaje, una columna nueva llamada “percent”con dos decimales.
P17 <- ggplot(data = Count_Union_Total_WDay , aes(x=week_day, y=n, fill = n ))+
geom_bar (stat = "identity")+
geom_text(aes(label=paste0(round(n,1), "\n (",round(percent,1),"%)"))
, vjust = -0.3 , size = 4 )+
expand_limits(y = max(Count_Union_Total_WDay$n) * 1.15) +
labs(title = "Uso de Bicicletas por Dia de la Semana 2019 y 2020",
x= "Dia de la Semana", y = "Tiempo Recorrido por Dia ",
caption = "Data: Empresa Motivate International Inc\nP17")+
theme(plot.title = element_text(hjust = 0.5),legend.position = "none")Nota.- expand_limits:funcion que amplia un eje (x o y) sin cambiar datos(etiquetas)
Visual
Seleccionamos variables usertype, ride_length,week_day, esta seleccion es para generar un grafico
Vemos su estructura
## tibble [791,956 × 3] (S3: tbl_df/tbl/data.frame)
## $ usertype : chr [1:791956] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ ride_length: 'difftime' num [1:791956] 23400 26460 49740 106980 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : chr [1:791956] "martes" "martes" "martes" "martes" ...
Se visualiza que la variable week_day, no contenga tildes con la funcion unique()
## [1] "martes" "miércoles" "jueves" "viernes" "sábado" "domingo"
## [7] "lunes"
Al ver que tiene tildes realice otras maneras me generaba N.A. y eliminaba asi que acudi y agradezco a la IA que me dio una solucion efectiva para los dias sabado y miercoles, por tal razo se utiliza sentencia que no genera N.A. en registros.
Sel_User_RidL_Wd_UTotal <- Sel_User_RidL_Wd_UTotal %>%
mutate(
week_day = iconv(week_day, from = "UTF-8", to = "ASCII//TRANSLIT"))Verficamos que la variable week_day, no contenga tildes con la funcion unique()
## [1] "martes" "miercoles" "jueves" "viernes" "sabado" "domingo"
## [7] "lunes"
Vemos su estructura
## tibble [791,956 × 3] (S3: tbl_df/tbl/data.frame)
## $ usertype : chr [1:791956] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ ride_length: 'difftime' num [1:791956] 23400 26460 49740 106980 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : chr [1:791956] "martes" "martes" "martes" "martes" ...
Para operar la tabla en el calculos o grafico ,se necesita cambiar de la tabla Sel_User_RidL_Wd_UTotal, la variable week_day, que es tipo caracter la transformamos a Factor por ser un listado fijo de los dias de la semana. Usamos la funcion unique porque los dias de la semana se repite
Sel_User_RidL_Wd_UTotal$week_day<-factor( Sel_User_RidL_Wd_UTotal$week_day,
levels=unique(Sel_User_RidL_Wd_UTotal$week_day))Nuevamente vemos su estructura
## tibble [791,956 × 3] (S3: tbl_df/tbl/data.frame)
## $ usertype : chr [1:791956] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ ride_length: 'difftime' num [1:791956] 23400 26460 49740 106980 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : Factor w/ 7 levels "martes","miercoles",..: 1 1 1 1 1 1 1 1 1 1 ...
Posterior en la misma tabla genera una nueva variable a partir de la variable ride_length, que tiene tipo de formato de tiempo difftime, esta crea una nueva variable denominada ride_length_sec y tambien la convierte en tipo de formato numerico, esto ayuda para que creamos grafico sin dificultad.
Sel_User_RidL_Wd_UTotal<- Sel_User_RidL_Wd_UTotal%>%
mutate(ride_length_sec = as.numeric(ride_length, units="secs"))Verificamos
## tibble [791,956 × 4] (S3: tbl_df/tbl/data.frame)
## $ usertype : chr [1:791956] "Subscriber" "Subscriber" "Subscriber" "Subscriber" ...
## $ ride_length : 'difftime' num [1:791956] 23400 26460 49740 106980 ...
## ..- attr(*, "units")= chr "secs"
## $ week_day : Factor w/ 7 levels "martes","miercoles",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ ride_length_sec: num [1:791956] 23400 26460 49740 106980 21840 ...
Limpiamos valores invalidos, porque se visualizo valores negativos y no tiene sentido el uso de tiempo de manera negativa, en el caso que exista y cambiamos de nombre a la tabla Sel_User_RidL_Wd_UTotal_Limpio de manera que funcione adecuadamente el para posteriores calculos y grafico
Realizamos el calculo de la media de tiempo de viaje, creando un group_by de variables usertype con week_day para sacar el promedio de la variable ride_length. Usamos la funcion drop se usa para eliminar (descartar) niveles, dimensiones o grupos que ya no # se necesita, es decir elimina el group_by luego de resumir.
Media_RidL <- Sel_User_RidL_Wd_UTotal_Limpio %>%
group_by(usertype, week_day) %>%
summarise(media_ridl = mean(ride_length_sec, na.rm = TRUE), .groups = "drop")Visual
Necesito crear otra tabla que me permita calcular el promedio de cada dia, que aporta cada cliente “usertype”y de la variable Week_day, para ello agrupamos momentaneamente y utilizaremos valores de la anterior tabla. Se realiza el calculo asi, porque son factores tipo texto su porcentaje se lo realiza de esta manera , porque es texto o factor. el siguiente calculo barca los valores de la otra tabla y genera promedio diario por tipo cliente
Media_RidL_WDay <- Media_RidL %>%
group_by(week_day) %>%
mutate(percent=media_ridl/sum(media_ridl)*100) %>%
ungroup()Visual
Generamos grafico P18 de Duracion Promedio de Viaje por Dia y Tipo de Cliente 2019 y 2020
P18<-ggplot(Media_RidL_WDay,
aes(x = week_day, y = media_ridl, fill = usertype)) +
geom_col(position = "dodge", width = 0.9) +
geom_text(aes(label = paste0(round(media_ridl,0),"\n(", round(percent, 1), "%)")),
position = position_dodge(width = 0.9), vjust =0, size = 2)+
scale_y_continuous(labels = scales::comma) +
labs(
title = "Duracion Promedio de Viaje por Dia y Tipo de Cliente 2019 y 2020",
x = "Dia de la Semana",
y = "Duracion Promedio (segundos)",
fill = "Tipo de Cliente",
caption = "Data: Empresa Motivate International Inc\nP18")+
theme_minimal() +
theme(plot.title = element_text(hjust = 0.5))Visual
Este apartado se centra en los factores relevantes del proceso, en el que resolvemos la pregunta principal del caso de estudio de la empresa Cyclistic Cuál es el problema que estás tratando de resolver?
Su Gerente y Directora de marketing, tiene mucha experiencia en el programa Cyclistic, y se respaldado de su equipo de trabajo en el que me incluyo, su labor y perseverancia en las campañas a traves de redes sociales ha dado beneficios, y desea continuar manteniendo con campañas de, para que los clientes casuales sean miembros permanentes del programa Cyclistic.
Para ello presento algunos motivos. Rodando por datos que le puede ayudar a su capaña durante los cuartiles de los años 2019 y 2020 visualice que Tipo de Clientes con su Porcentaje, muestra que “Miembros” permanentes son 720313 que correspondes aun 91%, mientras clientes “Casuales” tiene 71643 con el 9%. Podemos visualizar en la siguiente tabla
Rodando por el grafico de la tabla anterior, el 90.95% han decidido ser “Miembros”, ese particular se presenta porque el paquete para ser “Miembros” anual, es mucho mas economico en el tiempo, que un paquete individual, lo mas interesante es que las campañas en redes sociales han sido esitosas, comprende el cliente que le favorece ser cliente permanente del proyecto Cyclistic, veamos en el grafico
Sigamos rodando y vemos la trayectoria de recorrido, los datos muestra que en esos mismos periodos, muestra el resultado en la trayectoria que recorren clientes “Casuales” es de 4329619.9, siendo un 75.2% mientras que clientes “Miembros” es de 1424797, es el 24.8% de tiempo recorrido. Visualizamos en el grafico siguiente.
El 75.9% de clientes “Casuales” han recorrido mayores distancias en promedio, este particular, es porque la mayor parte de los clientes de edades que estudian o laboran medio tiempo.
Continuamos rodando por el siguiente grafico que corresponde solo al año 2019, la informacion que presenta es difiere con la que existe en el 2020, pero el año 2019 muestra que la densidad es decir la cantidad de clientes por edad esta a la izquierda de la media, es decir que va desde los 20 años hasta los 43 años, es el pico del grafico, no imoprta su genero, porque es similar su promedio. Esto ratifica lo que se expuso, anteriormente, que las distancias recorridas son justamente personas que estudian o laboran mediotiempo.
Hacemos un parada, porque se presenta una situacion interesante que en fin de semana que disminuye el numero de clientes en el uso de bicicletas lo podemos visualizar en el siguiente grafico. Observemos que entre semana de lunes a viernes la movilizacion de los clientes en bicicletas compartidas es mayor que los fines de semana, por lo que se ratica que los clientes o estudian o trabajan
Visual
Podemos ver la tabla en que los clientes en recorren en promedio bicicletas compartidas por dia
La tabla nos muestra el tipo d clientes (usertype), por dia (week_day) y en cifras la media por viaje en valor (media_ridl) y su porcentaje diario (percent) vemos que los clientes “casual” o “Customer” el dia domingo viaja en promedio 34782.59 segundos, que corresponde un 58.26% del que clientes “members” o “Subscriber” que viaja 24913.14 segundos; el dia juves los clientes “casual” viaja en promedio 185740.46 segundos con un 89.22%, mientra que el mismo dia los “member” viaja con un promedio de 22429.33 segundos con un 10.77% ; los dias lunes los clientes “casual” viaja en promedio 48450.25 segundos con un 67.26%, mientras que los”member” viaja en un promedio de 23578.59 corresponde un 32.73% ; los dias marte los clientes “casual” recorren 53189.96 segundos con un porcentaje del 68.97%, mientras que “member realizan 23929.78 con 31.02% ; los miercoles los”casual”recorre 58861.01 segundo, que corresponde 73.65% en contraste que clientes “member” recorre 21057.68 segundos con un porcentaje de 26.34% ; dia sabado recorren en promedio 99948.99 que representa un 76.53% y “member” recorren 30642.59 segundos con un porcentaje del 23.46% ; por ultimo los dias viernes los clientes “casual” viaja en promedio un 89842.03 segundo con un 77.37% mientra que “member” el mismo dia viaja 26273.05 segundos con un 22.62%
Tenemos una vista cuando se esta rodando del grafico que esta segmentado por tipo de cliente y su porcentaje por dia de la semana
Visual
Como podemos ver los clientes a pesar de que en cantidad de clientes
“casual” o tambien llamados “Customer” son menores, pero el recorrido
diario es superior casi en doble de viajes diarios que los “Member”
tambien llamados “Suscriber” y lo mas interseante es que su mayor
trayecto en dias laborables, lo que descarta que sean, que en el grafico
P17 sean turistas, como lo habiamos mensionado anterioremente, mas bien
son residentes de la ciudad d Chicago. Ademas sirve para ver que dias se
realiza un tipo de campaña por redes sociales.
Para completar vemos la cantidad de clientes por cada año y su diferencia y porcentaje
En el años 2019 habia 365069 y en el años 2020 existieron 426887, su diferencia es de 61818 usarios lo que corresponde un 16.93% de incremnto de clientes que ruedan en biclicletas compartidas de la empresa Cyclistic. Podemos verlo en el siguiente grafico
Visual
Rodando por el grafico vemos que sus datos tiene un crecimiento anual en
el 2020 del 16.9% con relacion a 2019, es bastante significativo, ya que
podriamos comparar con la economia general que esta alrededor del 4%
anual de crecimiento, eso indica que el programa Cyclistic esta
consolidado, su Gerente y Directora de Marketing , continuara generando
conciencia el uso de bicicletas compartidas.
Ahora que hemos concluido de rutear en el analisis, la Gerente y Directora de Marketing, considerara la informacion extraida y tomara mejor su decision, sin antes de recomendarle, que de acuerdo a los datos, podemos sugerir que la campaña que ella propone, sea dirigida a Clientes “Casuales” , que estudian o laboran, entre semana. Para que continuen rodando y generando conciencia sobre la salud y bienestar ambiental, el programa de Cyclistic es un gran aliado.