Welcome to the Cyclistic bike-share analysis case study! In this case study, we delve into the operations of Cyclistic, a prominent bike-share company based in Chicago. The objective of this analysis is to understand how different types of riders, including annual members and casual riders ,Utilize Cyclistic bikes and uncover insights that can inform the development of a new marketing strategy and make recommendations .
We will study on history of trip , we will follow the data analysis process, encompassing various steps such as ask, prepare, process, analyze, share, and act . By employing a data-driven approach, we will gain valuable insights into rider behavior and devise effective strategies to drive Cyclistic’s success in the bike-sharing market. We will perform on R to handle data and Tableau for data Visualization.
As a junior data analyst, and the director of marketing believes the company’s future success depends on maximizing the number of annual memberships. Therefore,our team wants to understand how casual riders and annual members use Cyclistic bikes differently. then i do marketing strategies to maximize annual memberships or persuade casual rudders to be annual memberships
Three questions will guide the future marketing program:
How do annual members and casual riders use Cyclistic bikes differently?
Why would casual riders buy Cyclistic annual memberships?
How can Cyclistic use digital media to influence casual riders to become members?
The director of marketing has assigned me the first question to answer: How do annual members and casual riders use Cyclistic bikes differently?
In this assignment, I will produce a report with the following deliverables:
1. A clear statement of the business task
2. A description of all data sources used
3. Documentation of any cleaning or manipulation of data
4. A summary of my analysis
5. Supporting visualizations and key findings
6. Your top three recommendations based on your analysis
Objective: Maximize the number of annual memberships by identifying and analyzing trends and patterns among casual riders and membership riders. The aim is to identify potential casual riders who could benefit from converting to annual memberships. Importantly, raising awareness of the membership program among casual riders is not necessary, as they are already familiar with the offering.
The stakeholders expect the creation of strategic marketing initiatives focused on converting casual riders into annual members. This requires a comprehensive understanding of:
The marketing team will utilize historical bike trip data from Cyclistic to identify relevant trends and insights.
### DATA TYPE check’
ROOOC Check
Sampling bias
Observer bias
Interpretation bias
Confirmation bias
Since Cyclistic is a fictional company, I will use Divvy’s, a bike-share program based in Chicago, data from May 2020 – April 2021 to complete this case study. To download the data, please use this link. This data was made public by Motivate International Inc, under this license. Due to data privacy issues, personal information has been removed or encrypted.
library(tidyverse) #helps wrangle data
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.0
## ✔ purrr 1.0.2
## ── 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
library(lubridate) #helps wrangle date attributes
library(ggplot2) #helps visualize data
library(dplyr) #helps clean data
library(tidyr) #helps clean data
# Load the trip dataset entire a year of 2023
data_2023_1<- read.csv("Dataset for Case Study 1/202301-divvy-tripdata.csv")
data_2023_2<- read.csv("Dataset for Case Study 1/202302-divvy-tripdata.csv")
data_2023_3<- read.csv("Dataset for Case Study 1/202303-divvy-tripdata.csv")
data_2023_4<- read.csv("Dataset for Case Study 1/202304-divvy-tripdata.csv")
data_2023_5<- read.csv("Dataset for Case Study 1/202305-divvy-tripdata.csv")
data_2023_6<- read.csv("Dataset for Case Study 1/202306-divvy-tripdata.csv")
data_2023_7<- read.csv("Dataset for Case Study 1/202307-divvy-tripdata.csv")
data_2023_8<- read.csv("Dataset for Case Study 1/202308-divvy-tripdata.csv")
data_2023_9<- read.csv("Dataset for Case Study 1/202309-divvy-tripdata.csv")
data_2023_10<- read.csv("Dataset for Case Study 1/202310-divvy-tripdata.csv")
data_2023_11<- read.csv("Dataset for Case Study 1/202311-divvy-tripdata.csv")
data_2023_12<- read.csv("Dataset for Case Study 1/202312-divvy-tripdata.csv")
# List of dataset names
dataset_names <- c(
"data_2023_1", "data_2023_2", "data_2023_3",
"data_2023_4", "data_2023_5", "data_2023_6",
"data_2023_7", "data_2023_8", "data_2023_9",
"data_2023_10", "data_2023_11", "data_2023_12"
)
# Iterate over each dataset and print its column names
for (dataset_name in dataset_names) {
cat("Columns for", dataset_name, ":\n")
print(colnames(get(dataset_name)))
cat("\n")
}
## Columns for data_2023_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"
##
## Columns for data_2023_2 :
## [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"
##
## Columns for data_2023_3 :
## [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"
##
## Columns for data_2023_4 :
## [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"
##
## Columns for data_2023_5 :
## [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"
##
## Columns for data_2023_6 :
## [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"
##
## Columns for data_2023_7 :
## [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"
##
## Columns for data_2023_8 :
## [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"
##
## Columns for data_2023_9 :
## [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"
##
## Columns for data_2023_10 :
## [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"
##
## Columns for data_2023_11 :
## [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"
##
## Columns for data_2023_12 :
## [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"
# Iterate over each dataset and print its structure using str()
for (dataset_name in dataset_names) {
dataset <- get(dataset_name)
cat("Structure for", dataset_name, ":\n")
str(dataset)
cat("\n")
}
## Structure for data_2023_1 :
## 'data.frame': 190301 obs. of 13 variables:
## $ ride_id : chr "F96D5A74A3E41399" "13CB7EB698CEDB88" "BD88A2E670661CE5" "C90792D034FED968" ...
## $ rideable_type : chr "electric_bike" "classic_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-01-21 20:05:42" "2023-01-10 15:37:36" "2023-01-02 07:51:57" "2023-01-22 10:52:58" ...
## $ ended_at : chr "2023-01-21 20:16:33" "2023-01-10 15:46:05" "2023-01-02 08:05:11" "2023-01-22 11:01:44" ...
## $ start_station_name: chr "Lincoln Ave & Fullerton Ave" "Kimbark Ave & 53rd St" "Western Ave & Lunt Ave" "Kimbark Ave & 53rd St" ...
## $ start_station_id : chr "TA1309000058" "TA1309000037" "RP-005" "TA1309000037" ...
## $ end_station_name : chr "Hampden Ct & Diversey Ave" "Greenwood Ave & 47th St" "Valli Produce - Evanston Plaza" "Greenwood Ave & 47th St" ...
## $ end_station_id : chr "202480.0" "TA1308000002" "599" "TA1308000002" ...
## $ start_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ start_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ end_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "casual" "member" ...
##
## Structure for data_2023_2 :
## 'data.frame': 190445 obs. of 13 variables:
## $ ride_id : chr "CBCD0D7777F0E45F" "F3EC5FCE5FF39DE9" "E54C1F27FA9354FF" "3D561E04F739CC45" ...
## $ rideable_type : chr "classic_bike" "electric_bike" "classic_bike" "electric_bike" ...
## $ started_at : chr "2023-02-14 11:59:42" "2023-02-15 13:53:48" "2023-02-19 11:10:57" "2023-02-26 16:12:05" ...
## $ ended_at : chr "2023-02-14 12:13:38" "2023-02-15 13:59:08" "2023-02-19 11:35:01" "2023-02-26 16:39:55" ...
## $ start_station_name: chr "Southport Ave & Clybourn Ave" "Clarendon Ave & Gordon Ter" "Southport Ave & Clybourn Ave" "Southport Ave & Clybourn Ave" ...
## $ start_station_id : chr "TA1309000030" "13379" "TA1309000030" "TA1309000030" ...
## $ end_station_name : chr "Clark St & Schiller St" "Sheridan Rd & Lawrence Ave" "Aberdeen St & Monroe St" "Franklin St & Adams St (Temp)" ...
## $ end_station_id : chr "TA1309000024" "TA1309000041" "13156" "TA1309000008" ...
## $ start_lat : num 41.9 42 41.9 41.9 41.8 ...
## $ start_lng : num -87.7 -87.6 -87.7 -87.7 -87.6 ...
## $ end_lat : num 41.9 42 41.9 41.9 41.8 ...
## $ end_lng : num -87.6 -87.7 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "casual" "casual" "member" "member" ...
##
## Structure for data_2023_3 :
## 'data.frame': 258678 obs. of 13 variables:
## $ ride_id : chr "6842AA605EE9FBB3" "F984267A75B99A8C" "FF7CF57CFE026D02" "6B61B916032CB6D6" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "classic_bike" "classic_bike" ...
## $ started_at : chr "2023-03-16 08:20:34" "2023-03-04 14:07:06" "2023-03-31 12:28:09" "2023-03-22 14:09:08" ...
## $ ended_at : chr "2023-03-16 08:22:52" "2023-03-04 14:15:31" "2023-03-31 12:38:47" "2023-03-22 14:24:51" ...
## $ start_station_name: chr "Clark St & Armitage Ave" "Public Rack - Kedzie Ave & Argyle St" "Orleans St & Chestnut St (NEXT Apts)" "Desplaines St & Kinzie St" ...
## $ start_station_id : chr "13146" "491" "620" "TA1306000003" ...
## $ end_station_name : chr "Larrabee St & Webster Ave" "" "Clark St & Randolph St" "Sheffield Ave & Kingsbury St" ...
## $ end_station_id : chr "13193" "" "TA1305000030" "13154" ...
## $ start_lat : num 41.9 42 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.7 -87.6 -87.6 -87.7 ...
## $ end_lat : num 41.9 42 41.9 41.9 41.9 ...
## $ end_lng : num -87.6 -87.7 -87.6 -87.7 -87.7 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_4 :
## 'data.frame': 426590 obs. of 13 variables:
## $ ride_id : chr "8FE8F7D9C10E88C7" "34E4ED3ADF1D821B" "5296BF07A2F77CB5" "40759916B76D5D52" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
## $ started_at : chr "2023-04-02 08:37:28" "2023-04-19 11:29:02" "2023-04-19 08:41:22" "2023-04-19 13:31:30" ...
## $ ended_at : chr "2023-04-02 08:41:37" "2023-04-19 11:52:12" "2023-04-19 08:43:22" "2023-04-19 13:35:09" ...
## $ start_station_name: chr "" "" "" "" ...
## $ start_station_id : chr "" "" "" "" ...
## $ end_station_name : chr "" "" "" "" ...
## $ end_station_id : chr "" "" "" "" ...
## $ start_lat : num 41.8 41.9 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.7 -87.7 -87.7 -87.7 ...
## $ end_lat : num 41.8 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.6 -87.7 -87.7 -87.7 -87.6 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_5 :
## 'data.frame': 604827 obs. of 13 variables:
## $ ride_id : chr "0D9FA920C3062031" "92485E5FB5888ACD" "FB144B3FC8300187" "DDEB93BC2CE9AA77" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-05-07 19:53:48" "2023-05-06 18:54:08" "2023-05-21 00:40:21" "2023-05-10 16:47:01" ...
## $ ended_at : chr "2023-05-07 19:58:32" "2023-05-06 19:03:35" "2023-05-21 00:44:36" "2023-05-10 16:59:52" ...
## $ start_station_name: chr "Southport Ave & Belmont Ave" "Southport Ave & Belmont Ave" "Halsted St & 21st St" "Carpenter St & Huron St" ...
## $ start_station_id : chr "13229" "13229" "13162" "13196" ...
## $ end_station_name : chr "" "" "" "Damen Ave & Cortland St" ...
## $ end_station_id : chr "" "" "" "13133" ...
## $ start_lat : num 41.9 41.9 41.9 41.9 42 ...
## $ start_lng : num -87.7 -87.7 -87.6 -87.7 -87.7 ...
## $ end_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.7 -87.7 -87.7 -87.7 -87.7 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_6 :
## 'data.frame': 719618 obs. of 13 variables:
## $ ride_id : chr "6F1682AC40EB6F71" "622A1686D64948EB" "3C88859D926253B4" "EAD8A5E0259DEC88" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
## $ started_at : chr "2023-06-05 13:34:12" "2023-06-05 01:30:22" "2023-06-20 18:15:49" "2023-06-19 14:56:00" ...
## $ ended_at : chr "2023-06-05 14:31:56" "2023-06-05 01:33:06" "2023-06-20 18:32:05" "2023-06-19 15:00:35" ...
## $ start_station_name: chr "" "" "" "" ...
## $ start_station_id : chr "" "" "" "" ...
## $ end_station_name : chr "" "" "" "" ...
## $ end_station_id : chr "" "" "" "" ...
## $ start_lat : num 41.9 41.9 42 42 42 ...
## $ start_lng : num -87.7 -87.7 -87.7 -87.7 -87.7 ...
## $ end_lat : num 41.9 41.9 41.9 42 42 ...
## $ end_lng : num -87.7 -87.7 -87.6 -87.7 -87.7 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_7 :
## 'data.frame': 767650 obs. of 13 variables:
## $ ride_id : chr "9340B064F0AEE130" "D1460EE3CE0D8AF8" "DF41BE31B895A25E" "9624A293749EF703" ...
## $ rideable_type : chr "electric_bike" "classic_bike" "classic_bike" "electric_bike" ...
## $ started_at : chr "2023-07-23 20:06:14" "2023-07-23 17:05:07" "2023-07-23 10:14:53" "2023-07-21 08:27:44" ...
## $ ended_at : chr "2023-07-23 20:22:44" "2023-07-23 17:18:37" "2023-07-23 10:24:29" "2023-07-21 08:32:40" ...
## $ start_station_name: chr "Kedzie Ave & 110th St" "Western Ave & Walton St" "Western Ave & Walton St" "Racine Ave & Randolph St" ...
## $ start_station_id : chr "20204" "KA1504000103" "KA1504000103" "13155" ...
## $ end_station_name : chr "Public Rack - Racine Ave & 109th Pl" "Milwaukee Ave & Grand Ave" "Damen Ave & Pierce Ave" "Clinton St & Madison St" ...
## $ end_station_id : chr "877" "13033" "TA1305000041" "TA1305000032" ...
## $ start_lat : num 41.7 41.9 41.9 41.9 42 ...
## $ start_lng : num -87.7 -87.7 -87.7 -87.7 -87.7 ...
## $ end_lat : num 41.7 41.9 41.9 41.9 42 ...
## $ end_lng : num -87.7 -87.6 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_8 :
## 'data.frame': 771693 obs. of 13 variables:
## $ ride_id : chr "903C30C2D810A53B" "F2FB18A98E110A2B" "D0DEC7C94E4663DA" "E0DDDC5F84747ED9" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
## $ started_at : chr "2023-08-19 15:41:53" "2023-08-18 15:30:18" "2023-08-30 16:15:08" "2023-08-30 16:24:07" ...
## $ ended_at : chr "2023-08-19 15:53:36" "2023-08-18 15:45:25" "2023-08-30 16:27:37" "2023-08-30 16:33:34" ...
## $ start_station_name: chr "LaSalle St & Illinois St" "Clark St & Randolph St" "Clark St & Randolph St" "Wells St & Elm St" ...
## $ start_station_id : chr "13430" "TA1305000030" "TA1305000030" "KA1504000135" ...
## $ end_station_name : chr "Clark St & Elm St" "" "" "" ...
## $ end_station_id : chr "TA1307000039" "" "" "" ...
## $ start_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.6 -87.6 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.6 -87.6 -87.6 -87.6 -87.7 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_9 :
## 'data.frame': 666371 obs. of 13 variables:
## $ ride_id : chr "011C1903BF4E2E28" "87DB80E048A1BF9F" "7C2EB7AF669066E3" "57D197B010269CE3" ...
## $ rideable_type : chr "classic_bike" "classic_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-09-23 00:27:50" "2023-09-02 09:26:43" "2023-09-25 18:30:11" "2023-09-13 15:30:49" ...
## $ ended_at : chr "2023-09-23 00:33:27" "2023-09-02 09:38:19" "2023-09-25 18:41:39" "2023-09-13 15:39:18" ...
## $ start_station_name: chr "Halsted St & Wrightwood Ave" "Clark St & Drummond Pl" "Financial Pl & Ida B Wells Dr" "Clark St & Drummond Pl" ...
## $ start_station_id : chr "TA1309000061" "TA1307000142" "SL-010" "TA1307000142" ...
## $ end_station_name : chr "Sheffield Ave & Wellington Ave" "Racine Ave & Fullerton Ave" "Racine Ave & 15th St" "Racine Ave & Belmont Ave" ...
## $ end_station_id : chr "TA1307000052" "TA1306000026" "13304" "TA1308000019" ...
## $ start_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.6 -87.6 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.7 -87.7 -87.7 -87.7 -87.7 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_10 :
## 'data.frame': 537113 obs. of 13 variables:
## $ ride_id : chr "4449097279F8BBE7" "9CF060543CA7B439" "667F21F4D6BDE69C" "F92714CC6B019B96" ...
## $ rideable_type : chr "classic_bike" "electric_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-10-08 10:36:26" "2023-10-11 17:23:59" "2023-10-12 07:02:33" "2023-10-24 19:13:03" ...
## $ ended_at : chr "2023-10-08 10:49:19" "2023-10-11 17:36:08" "2023-10-12 07:06:53" "2023-10-24 19:18:29" ...
## $ start_station_name: chr "Orleans St & Chestnut St (NEXT Apts)" "Desplaines St & Kinzie St" "Orleans St & Chestnut St (NEXT Apts)" "Desplaines St & Kinzie St" ...
## $ start_station_id : chr "620" "TA1306000003" "620" "TA1306000003" ...
## $ end_station_name : chr "Sheffield Ave & Webster Ave" "Sheffield Ave & Webster Ave" "Franklin St & Lake St" "Franklin St & Lake St" ...
## $ end_station_id : chr "TA1309000033" "TA1309000033" "TA1307000111" "TA1307000111" ...
## $ start_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.6 -87.6 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.7 -87.7 -87.6 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_11 :
## 'data.frame': 362518 obs. of 13 variables:
## $ ride_id : chr "4EAD8F1AD547356B" "6322270563BF5470" "B37BDE091ECA38E0" "CF0CA5DD26E4F90E" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-11-30 21:50:05" "2023-11-03 09:44:02" "2023-11-30 11:39:44" "2023-11-08 10:01:45" ...
## $ ended_at : chr "2023-11-30 22:13:27" "2023-11-03 10:17:15" "2023-11-30 11:40:08" "2023-11-08 10:27:05" ...
## $ start_station_name: chr "Millennium Park" "Broadway & Sheridan Rd" "State St & Pearson St" "Theater on the Lake" ...
## $ start_station_id : chr "13008" "13323" "TA1307000061" "TA1308000001" ...
## $ end_station_name : chr "Pine Grove Ave & Waveland Ave" "Broadway & Sheridan Rd" "State St & Pearson St" "Theater on the Lake" ...
## $ end_station_id : chr "TA1307000150" "13323" "TA1307000061" "TA1308000001" ...
## $ start_lat : num 41.9 42 41.9 41.9 41.9 ...
## $ start_lng : num -87.6 -87.7 -87.6 -87.6 -87.6 ...
## $ end_lat : num 41.9 42 41.9 41.9 41.9 ...
## $ end_lng : num -87.6 -87.6 -87.6 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "member" "member" ...
##
## Structure for data_2023_12 :
## 'data.frame': 224073 obs. of 13 variables:
## $ ride_id : chr "C9BD54F578F57246" "CDBD92F067FA620E" "ABC0858E52CBFC84" "F44B6F0E8F76DC90" ...
## $ rideable_type : chr "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
## $ started_at : chr "2023-12-02 18:44:01" "2023-12-02 18:48:19" "2023-12-24 01:56:32" "2023-12-24 10:58:12" ...
## $ ended_at : chr "2023-12-02 18:47:51" "2023-12-02 18:54:48" "2023-12-24 02:04:09" "2023-12-24 11:03:04" ...
## $ start_station_name: chr "" "" "" "" ...
## $ start_station_id : chr "" "" "" "" ...
## $ end_station_name : chr "" "" "" "" ...
## $ end_station_id : chr "" "" "" "" ...
## $ start_lat : num 41.9 41.9 41.9 42 41.9 ...
## $ start_lng : num -87.7 -87.7 -87.6 -87.7 -87.6 ...
## $ end_lat : num 41.9 41.9 41.9 41.9 41.9 ...
## $ end_lng : num -87.7 -87.6 -87.6 -87.7 -87.6 ...
## $ member_casual : chr "member" "member" "member" "member" ...
library(dplyr)
# List of dataset names
dataset_names <- c(
"data_2023_1", "data_2023_2", "data_2023_3",
"data_2023_4", "data_2023_5", "data_2023_6",
"data_2023_7", "data_2023_8", "data_2023_9",
"data_2023_10", "data_2023_11", "data_2023_12"
)
# Read and combine all datasets
combined_data <- bind_rows(
lapply(dataset_names, function(dataset_name) get(dataset_name))
)
colnames(combined_data)
## [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"
nrow(combined_data) #How many rows are in data frame?
## [1] 5719877
dim(combined_data) #Dimensions of the data frame?
## [1] 5719877 13
head(combined_data) #See the first 6 rows of data frame.
## ride_id rideable_type started_at ended_at
## 1 F96D5A74A3E41399 electric_bike 2023-01-21 20:05:42 2023-01-21 20:16:33
## 2 13CB7EB698CEDB88 classic_bike 2023-01-10 15:37:36 2023-01-10 15:46:05
## 3 BD88A2E670661CE5 electric_bike 2023-01-02 07:51:57 2023-01-02 08:05:11
## 4 C90792D034FED968 classic_bike 2023-01-22 10:52:58 2023-01-22 11:01:44
## 5 3397017529188E8A classic_bike 2023-01-12 13:58:01 2023-01-12 14:13:20
## 6 58E68156DAE3E311 electric_bike 2023-01-31 07:18:03 2023-01-31 07:21:16
## start_station_name start_station_id end_station_name
## 1 Lincoln Ave & Fullerton Ave TA1309000058 Hampden Ct & Diversey Ave
## 2 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 3 Western Ave & Lunt Ave RP-005 Valli Produce - Evanston Plaza
## 4 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 5 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 6 Lakeview Ave & Fullerton Pkwy TA1309000019 Hampden Ct & Diversey Ave
## end_station_id start_lat start_lng end_lat end_lng member_casual
## 1 202480.0 41.92407 -87.64628 41.93000 -87.64000 member
## 2 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 3 599 42.00857 -87.69048 42.03974 -87.69941 casual
## 4 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 5 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 6 202480.0 41.92607 -87.63886 41.93000 -87.64000 member
str(combined_data) #See list of columns and data types (numeric, character, etc)
## 'data.frame': 5719877 obs. of 13 variables:
## $ ride_id : chr "F96D5A74A3E41399" "13CB7EB698CEDB88" "BD88A2E670661CE5" "C90792D034FED968" ...
## $ rideable_type : chr "electric_bike" "classic_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-01-21 20:05:42" "2023-01-10 15:37:36" "2023-01-02 07:51:57" "2023-01-22 10:52:58" ...
## $ ended_at : chr "2023-01-21 20:16:33" "2023-01-10 15:46:05" "2023-01-02 08:05:11" "2023-01-22 11:01:44" ...
## $ start_station_name: chr "Lincoln Ave & Fullerton Ave" "Kimbark Ave & 53rd St" "Western Ave & Lunt Ave" "Kimbark Ave & 53rd St" ...
## $ start_station_id : chr "TA1309000058" "TA1309000037" "RP-005" "TA1309000037" ...
## $ end_station_name : chr "Hampden Ct & Diversey Ave" "Greenwood Ave & 47th St" "Valli Produce - Evanston Plaza" "Greenwood Ave & 47th St" ...
## $ end_station_id : chr "202480.0" "TA1308000002" "599" "TA1308000002" ...
## $ start_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ start_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ end_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "casual" "member" ...
# You can also confirm each columns' data type here
summary(combined_data) #Statistical summary of data. Mainly for numerics
## ride_id rideable_type started_at ended_at
## Length:5719877 Length:5719877 Length:5719877 Length:5719877
## 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:5719877 Length:5719877 Length:5719877 Length:5719877
## 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.63 Min. :-87.94 Min. : 0.00 Min. :-88.16
## 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. :42.07 Max. :-87.46 Max. :42.18 Max. : 0.00
## NA's :6990 NA's :6990
## member_casual
## Length:5719877
## Class :character
## Mode :character
##
##
##
##
#Confirmed there are 5006 NA columns in end_lat and end_lat
# Add columns that list the date, month, day, and year of each ride as we might need to aggregate ride data for each month, day, or year.
combined_data$date <- as.Date(combined_data$started_at) #The default format is yyyy-mm-dd
combined_data$month <- format(as.Date(combined_data$date), "%m")
combined_data$day <- format(as.Date(combined_data$date), "%d")
combined_data$year <- format(as.Date(combined_data$date), "%Y")
combined_data$day_of_week <- format(as.Date(combined_data$date), "%A")
colnames(combined_data)
## [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" "date" "month"
## [16] "day" "year" "day_of_week"
head(combined_data) #See the first 6 rows of data frame.
## ride_id rideable_type started_at ended_at
## 1 F96D5A74A3E41399 electric_bike 2023-01-21 20:05:42 2023-01-21 20:16:33
## 2 13CB7EB698CEDB88 classic_bike 2023-01-10 15:37:36 2023-01-10 15:46:05
## 3 BD88A2E670661CE5 electric_bike 2023-01-02 07:51:57 2023-01-02 08:05:11
## 4 C90792D034FED968 classic_bike 2023-01-22 10:52:58 2023-01-22 11:01:44
## 5 3397017529188E8A classic_bike 2023-01-12 13:58:01 2023-01-12 14:13:20
## 6 58E68156DAE3E311 electric_bike 2023-01-31 07:18:03 2023-01-31 07:21:16
## start_station_name start_station_id end_station_name
## 1 Lincoln Ave & Fullerton Ave TA1309000058 Hampden Ct & Diversey Ave
## 2 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 3 Western Ave & Lunt Ave RP-005 Valli Produce - Evanston Plaza
## 4 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 5 Kimbark Ave & 53rd St TA1309000037 Greenwood Ave & 47th St
## 6 Lakeview Ave & Fullerton Pkwy TA1309000019 Hampden Ct & Diversey Ave
## end_station_id start_lat start_lng end_lat end_lng member_casual
## 1 202480.0 41.92407 -87.64628 41.93000 -87.64000 member
## 2 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 3 599 42.00857 -87.69048 42.03974 -87.69941 casual
## 4 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 5 TA1308000002 41.79957 -87.59475 41.80983 -87.59938 member
## 6 202480.0 41.92607 -87.63886 41.93000 -87.64000 member
## date month day year day_of_week
## 1 2023-01-21 01 21 2023 Saturday
## 2 2023-01-10 01 10 2023 Tuesday
## 3 2023-01-02 01 02 2023 Monday
## 4 2023-01-22 01 22 2023 Sunday
## 5 2023-01-12 01 12 2023 Thursday
## 6 2023-01-31 01 31 2023 Tuesday
str(combined_data)
## 'data.frame': 5719877 obs. of 18 variables:
## $ ride_id : chr "F96D5A74A3E41399" "13CB7EB698CEDB88" "BD88A2E670661CE5" "C90792D034FED968" ...
## $ rideable_type : chr "electric_bike" "classic_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-01-21 20:05:42" "2023-01-10 15:37:36" "2023-01-02 07:51:57" "2023-01-22 10:52:58" ...
## $ ended_at : chr "2023-01-21 20:16:33" "2023-01-10 15:46:05" "2023-01-02 08:05:11" "2023-01-22 11:01:44" ...
## $ start_station_name: chr "Lincoln Ave & Fullerton Ave" "Kimbark Ave & 53rd St" "Western Ave & Lunt Ave" "Kimbark Ave & 53rd St" ...
## $ start_station_id : chr "TA1309000058" "TA1309000037" "RP-005" "TA1309000037" ...
## $ end_station_name : chr "Hampden Ct & Diversey Ave" "Greenwood Ave & 47th St" "Valli Produce - Evanston Plaza" "Greenwood Ave & 47th St" ...
## $ end_station_id : chr "202480.0" "TA1308000002" "599" "TA1308000002" ...
## $ start_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ start_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ end_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "casual" "member" ...
## $ date : Date, format: "2023-01-21" "2023-01-10" ...
## $ month : chr "01" "01" "01" "01" ...
## $ day : chr "21" "10" "02" "22" ...
## $ year : chr "2023" "2023" "2023" "2023" ...
## $ day_of_week : chr "Saturday" "Tuesday" "Monday" "Sunday" ...
# Add a "ride_length" calculation to all_trips (in seconds) so that I can compare ride length for each ride
# https://stat.ethz.ch/R-manual/R-devel/library/base/html/difftime.html
combined_data$ride_length <- difftime(combined_data$ended_at,combined_data$started_at)
# Convert "ride_length" from Double to numeric so we can run calculations on the data
combined_data$ride_length <- as.numeric(as.character(combined_data$ride_length))
is.numeric(combined_data$ride_length)
## [1] TRUE
# Remove "bad" data
# The dataframe includes a few hundred entries when bikes were taken out of docks and checked for quality by Divvy or ride_length was negative
#Create a new data frame without records that have ride length <= zero minute OR > 1440 minutes
combined_data_v2 <- combined_data[!(combined_data$ride_length <= 0 | combined_data$ride_length > 1440),]
#Check the new data frame
dim(combined_data_v2)
## [1] 4902180 19
View(combined_data_v2)
summary(combined_data_v2)
## ride_id rideable_type started_at ended_at
## Length:4902180 Length:4902180 Length:4902180 Length:4902180
## 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:4902180 Length:4902180 Length:4902180 Length:4902180
## 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.92 Min. : 0.00 Min. :-87.99
## 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.65
## 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. :42.07 Max. :-87.52 Max. :42.09 Max. : 0.00
## NA's :146 NA's :146
## member_casual date month day
## Length:4902180 Min. :2023-01-01 Length:4902180 Length:4902180
## Class :character 1st Qu.:2023-05-18 Class :character Class :character
## Mode :character Median :2023-07-20 Mode :character Mode :character
## Mean :2023-07-15
## 3rd Qu.:2023-09-19
## Max. :2023-12-31
##
## year day_of_week ride_length
## Length:4902180 Length:4902180 Min. : 1.0
## Class :character Class :character 1st Qu.: 295.0
## Mode :character Mode :character Median : 492.0
## Mean : 560.1
## 3rd Qu.: 778.0
## Max. :1440.0
##
#Confirmed the total number of rows is 4,902,180 (down from 5,719,877 - decreased by 10% - significant but necessary removals.
#1,241 NAs Remains in end_lat and end_long
1. Remove NA data from the all_trips_v2 to get accurate data.
# Remove rows with NAs using na.omit()
combined_data_v2 <- na.omit(combined_data_v2)
# Check for NAs in the dataframe
any_na <- anyNA(combined_data_v2)
print(any_na)
## [1] FALSE
1. Remove duplicated ID as I confirmed ride ID is associated with each ride, not riders.
#Remove duplicated ID (confirmed different ride_id is assigned for every rides even if same rider uses this service):
combined_data_v3 <- combined_data_v2[!duplicated(combined_data_v2$ride_id),]
dim(combined_data_v2)
## [1] 4902034 19
# Confirmed 4,902,034 remained (Original data has 4,902,180 >>> Valid)
Data Cleaning/Validation process has been completed at this point.
Next, I am going to create additional columns for further analysis.
# Load the geosphere package
library(geosphere)
## Warning: package 'geosphere' was built under R version 4.3.3
#Find out the distance for each ride:
combined_data_v3$ride_distance <- distGeo(matrix(c(combined_data_v3$start_lng, combined_data_v3$start_lat), ncol = 2), matrix(c(combined_data_v3$end_lng, combined_data_v3$end_lat), ncol = 2))
View(combined_data_v3)
str(combined_data_v3)
## 'data.frame': 4902034 obs. of 20 variables:
## $ ride_id : chr "F96D5A74A3E41399" "13CB7EB698CEDB88" "BD88A2E670661CE5" "C90792D034FED968" ...
## $ rideable_type : chr "electric_bike" "classic_bike" "electric_bike" "classic_bike" ...
## $ started_at : chr "2023-01-21 20:05:42" "2023-01-10 15:37:36" "2023-01-02 07:51:57" "2023-01-22 10:52:58" ...
## $ ended_at : chr "2023-01-21 20:16:33" "2023-01-10 15:46:05" "2023-01-02 08:05:11" "2023-01-22 11:01:44" ...
## $ start_station_name: chr "Lincoln Ave & Fullerton Ave" "Kimbark Ave & 53rd St" "Western Ave & Lunt Ave" "Kimbark Ave & 53rd St" ...
## $ start_station_id : chr "TA1309000058" "TA1309000037" "RP-005" "TA1309000037" ...
## $ end_station_name : chr "Hampden Ct & Diversey Ave" "Greenwood Ave & 47th St" "Valli Produce - Evanston Plaza" "Greenwood Ave & 47th St" ...
## $ end_station_id : chr "202480.0" "TA1308000002" "599" "TA1308000002" ...
## $ start_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ start_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ end_lat : num 41.9 41.8 42 41.8 41.8 ...
## $ end_lng : num -87.6 -87.6 -87.7 -87.6 -87.6 ...
## $ member_casual : chr "member" "member" "casual" "member" ...
## $ date : Date, format: "2023-01-21" "2023-01-10" ...
## $ month : chr "01" "01" "01" "01" ...
## $ day : chr "21" "10" "02" "22" ...
## $ year : chr "2023" "2023" "2023" "2023" ...
## $ day_of_week : chr "Saturday" "Tuesday" "Monday" "Sunday" ...
## $ ride_length : num 651 509 794 526 919 193 840 561 747 753 ...
## $ ride_distance : num 839 1204 3540 1204 1204 ...
## - attr(*, "na.action")= 'omit' Named int [1:146] 66648 113756 115015 202485 268133 378866 399457 542862 646262 655015 ...
## ..- attr(*, "names")= chr [1:146] "71703" "122586" "123948" "218177" ...
#Assign the correct order to each day of the week
combined_data_v3$day_of_week <-
ordered(combined_data_v3$day_of_week, levels = c('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'))
combined_data_v3 %>%
group_by(member_casual, day_of_week) %>%
summarise(number_of_ride = n(), .groups = 'drop') %>%
arrange(day_of_week)
## # A tibble: 14 × 3
## member_casual day_of_week number_of_ride
## <chr> <ord> <int>
## 1 casual Monday 183159
## 2 member Monday 451692
## 3 casual Tuesday 200147
## 4 member Tuesday 525956
## 5 casual Wednesday 206960
## 6 member Wednesday 537335
## 7 casual Thursday 222990
## 8 member Thursday 538909
## 9 casual Friday 244873
## 10 member Friday 481725
## 11 casual Saturday 297304
## 12 member Saturday 413810
## 13 casual Sunday 240627
## 14 member Sunday 356547
# Summary statistics
summary_stats <- combined_data_v3 %>%
group_by(member_casual) %>%
summarise(
total_rides = n(),
average_ride_length = mean(ride_length),
average_ride_distance = mean(ride_distance)
)
print(summary_stats)
## # A tibble: 2 × 4
## member_casual total_rides average_ride_length average_ride_distance
## <chr> <int> <dbl> <dbl>
## 1 casual 1596060 612. 1737.
## 2 member 3305974 535. 1792.
# Visualizations
# Distribution of rides by member type
rides_distribution <- combined_data_v3 %>%
group_by(member_casual) %>%
summarise(total_rides = n())
# Plot
# Plot
ggplot(rides_distribution, aes(x = member_casual, y = total_rides, fill = member_casual)) +
geom_bar(stat = "identity") +
labs(title = "Distribution of Rides by Member Type",
x = "Member Type",
y = "Total Rides") +
theme_minimal()
options(tibble.print_max = Inf)
combined_data_v3$month <- ordered(combined_data_v3$month,
levels = c('05', '06', '07', '08', '09', '10', '11', '12', '01', '02', '03', '04'))
result <- combined_data_v3 %>%
group_by(member_casual, month) %>%
summarise(number_of_ride = n(), .groups = 'drop') %>%
arrange(month)
print(result)
## # A tibble: 24 × 3
## member_casual month number_of_ride
## <chr> <ord> <int>
## 1 casual 05 174691
## 2 member 05 330358
## 3 casual 06 227618
## 4 member 06 371516
## 5 casual 07 244366
## 6 member 07 384212
## 7 casual 08 235613
## 8 member 08 407410
## 9 casual 09 199955
## 10 member 09 361716
## 11 casual 10 143014
## 12 member 10 329680
## 13 casual 11 83949
## 14 member 11 244576
## 15 casual 12 45465
## 16 member 12 160705
## 17 casual 01 36061
## 18 member 01 141107
## 19 casual 02 37004
## 20 member 02 137087
## 21 casual 03 53963
## 22 member 03 183713
## 23 casual 04 114361
## 24 member 04 253894
Now, I would like to find out whether ride_length can be different depends on rider type.
aggregate(combined_data_v3$ride_length ~ combined_data_v3$member_casual + combined_data_v3$day_of_week, FUN=mean)
## combined_data_v3$member_casual combined_data_v3$day_of_week
## 1 casual Monday
## 2 member Monday
## 3 casual Tuesday
## 4 member Tuesday
## 5 casual Wednesday
## 6 member Wednesday
## 7 casual Thursday
## 8 member Thursday
## 9 casual Friday
## 10 member Friday
## 11 casual Saturday
## 12 member Saturday
## 13 casual Sunday
## 14 member Sunday
## combined_data_v3$ride_length
## 1 592.5435
## 2 519.9265
## 3 586.8119
## 4 528.8072
## 5 583.3356
## 6 531.1687
## 7 589.8024
## 8 532.8086
## 9 609.1766
## 10 530.4884
## 11 651.8541
## 12 559.4634
## 13 645.3022
## 14 551.6448
combined_data_v3 %>%
group_by(member_casual, month) %>%
summarise(average_ride_length = mean(ride_length), .groups = 'drop') %>%
arrange(month)
## # A tibble: 24 × 3
## member_casual month average_ride_length
## <chr> <ord> <dbl>
## 1 casual 05 625.
## 2 member 05 547.
## 3 casual 06 640.
## 4 member 06 565.
## 5 casual 07 646.
## 6 member 07 569.
## 7 casual 08 643.
## 8 member 08 570.
## 9 casual 09 627.
## 10 member 09 558.
## 11 casual 10 583.
## 12 member 10 526.
## 13 casual 11 549.
## 14 member 11 507.
## 15 casual 12 527.
## 16 member 12 497.
## 17 casual 01 499.
## 18 member 01 469.
## 19 casual 02 527.
## 20 member 02 475.
## 21 casual 03 529.
## 22 member 03 478.
## 23 casual 04 588.
## 24 member 04 510.
Membership rider’s trip is longer than casual ones regardless of the season or day
All users take longer trips over weekend and and the last of summer season
Next, check whether how each type of rider use the bike by looking at ride distance.
combined_data_v3 %>%
group_by(member_casual, day_of_week) %>%
summarise(distance_of_ride = mean(ride_distance), .groups = 'drop') %>%
arrange(day_of_week)
## # A tibble: 14 × 3
## member_casual day_of_week distance_of_ride
## <chr> <ord> <dbl>
## 1 casual Monday 1690.
## 2 member Monday 1756.
## 3 casual Tuesday 1739.
## 4 member Tuesday 1792.
## 5 casual Wednesday 1749.
## 6 member Wednesday 1805.
## 7 casual Thursday 1795.
## 8 member Thursday 1822.
## 9 casual Friday 1723.
## 10 member Friday 1764.
## 11 casual Saturday 1732.
## 12 member Saturday 1806.
## 13 casual Sunday 1725.
## 14 member Sunday 1790.
combined_data_v3 %>%
group_by(member_casual, month) %>%
summarise(distance_of_ride = mean(ride_distance), .groups = 'drop') %>%
arrange(month)
## # A tibble: 24 × 3
## member_casual month distance_of_ride
## <chr> <ord> <dbl>
## 1 casual 05 1757.
## 2 member 05 1843.
## 3 casual 06 1845.
## 4 member 06 1920.
## 5 casual 07 1775.
## 6 member 07 1884.
## 7 casual 08 1787.
## 8 member 08 1872.
## 9 casual 09 1762.
## 10 member 09 1845.
## 11 casual 10 1687.
## 12 member 10 1762.
## 13 casual 11 1622.
## 14 member 11 1703.
## 15 casual 12 1548.
## 16 member 12 1672.
## 17 casual 01 1504.
## 18 member 01 1564.
## 19 casual 02 1562.
## 20 member 02 1586.
## 21 casual 03 1579.
## 22 member 03 1640.
## 23 casual 04 1687.
## 24 member 04 1738.
Finaly, in order to support my assumption, let’s find out how many riders use the same bike station for start point and end point (ride_distance = 0).
combined_data_v3 %>%
group_by(member_casual) %>%
summarize(number_of_rides = n() , .groups = 'drop')
## # A tibble: 2 × 2
## member_casual number_of_rides
## <chr> <int>
## 1 casual 1596060
## 2 member 3305974
combined_data_v3 %>%
group_by(member_casual) %>%
filter(ride_distance < 1) %>%
summarize(number_of_rides = n() , .groups = 'drop')
## # A tibble: 2 × 2
## member_casual number_of_rides
## <chr> <int>
## 1 casual 102927
## 2 member 110657
Proportions of rides returning to the start point were calculated as follows:
Casual riders:
\[
\frac{102,927}{1,596,060} \times 100 \approx 6.45\%
\]
Membership riders:
\[
\frac{110,657}{3,305,974} \times 100 \approx 3.35\%
\]
Casual riders show a higher tendency for short trips that begin and end at the same location, which could indicate recreational or exploratory use. Membership riders’ lower proportion of such trips suggests more practical and routine uses, possibly related to commuting. These insights can help tailor marketing strategies to convert casual riders into members by highlighting the benefits of membership for regular commuting.