<jupyter_start><jupyter_text>Data Analysis of the Ford GoBike's trip data  Investigation OverviewIn this investigation we will look into aspects of how long is the typical bike trip duration?During what weekdays does bike trips occur?Is is possible to see sightseeing bike trips?During which hours of the day does bike trips start? Dataset OverviewThe data consist of over 2 million bike trips collected between january 2018 and february 2019. The attributes include start and stop station with date and time, user type. No data points was removed from the datasets that where downloaded from the Ford GoBike's trip data for public use.<jupyter_code>import os
import pandas as pd
from datetime import timedelta
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="dark", color_codes=True, context='talk', palette='muted', rc={"lines.linewidth": 2})
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
DATA_DIR = 'data'
IMAGES_DIR = 'images'

def ensure_dir(file_path=IMAGES_DIR):
    """
    Ensure directory exists or create it.
    :param file_path: directory path
    :return: 
    """
    if not os.path.exists(file_path):
        os.makedirs(file_path)


# load data source files and make one DataFrame
tripdata_files = [file for file in os.listdir(DATA_DIR) if file.endswith('.csv') and os.path.isfile(os.path.join(DATA_DIR, file))]
dataframes = [pd.read_csv(os.path.join(DATA_DIR, file)) for file in tripdata_files]

# create master dataframe and delete the temporary variables
bikeshare_df = pd.concat(dataframes)
del tripdata_files
del dataframes

# fix data types on dataframe
bikeshare_df['start_time'] = pd.to_datetime(bikeshare_df['start_time'])
bikeshare_df['end_time'] = pd.to_datetime(bikeshare_df['end_time'])
bikeshare_df['duration'] = bikeshare_df['duration_sec'].apply(lambda x: timedelta(seconds=x))
bikeshare_df['user_type'] = bikeshare_df['user_type'].astype('category')
bikeshare_df['bike_share_for_all_trip'] = bikeshare_df['bike_share_for_all_trip'].astype('category')
bikeshare_df['member_gender'].fillna('Other', inplace=True)
bikeshare_df['member_gender'] = bikeshare_df['member_gender'].astype('category')

# dataframe copy with three columns and a new with the name of the weekday
userstart = bikeshare_df[['user_type', 'start_time', 'duration_sec']].copy()
userstart['weekday'] = userstart.start_time.dt.weekday_name<jupyter_output><empty_output><jupyter_text>1. How long is the typical bike trip duration?  The bike rental duration contains some extreme values. But the most common bike rental is less than 10 minutes in lenght.I'm not able to explain why bike rental durations have several extreme values of hours and even days. But maybe this could be explained by bike getting flat tires,  other mechanical failures or even accidents that prevented the rider to return the bike? These questions can't be answered from the dataset.<jupyter_code># cut the duration_sec into eight discrete intervals
# and count values for each interval
# then generate a bar plot that is also saved to disk.

bins = [0, 300, 600, 900, 1800, 3600, 7200, 14400, 86400]
labels = ['< 5 min', '< 10 min', '< 15 min', '< 30 min', '< 1 hour', '< 2 hours', '< 4 hours', '24 hours or more']

duration_quartiles = pd.cut(bikeshare_df['duration_sec'], bins=bins, labels=labels)
binned_duration = duration_quartiles.value_counts(sort=False)

fig, ax = plt.subplots(figsize=(12, 8))
sns.barplot(binned_duration.index, binned_duration, color='steelblue', ax=ax)
ax.set(title='Bike rentals duration binned', xlabel='', ylabel='Frequencey of bike rentals')
ax.tick_params(axis='x', labelrotation=90)

ensure_dir(IMAGES_DIR)
plt.tight_layout()
plt.savefig(os.path.join(IMAGES_DIR, 'bike_rental_duration.jpg'))<jupyter_output><empty_output><jupyter_text>2. During what days of the week does bike rentals occur?  There are two different user types Customer and Subscribers and Customers are 14 % of renters. Bike rentals mostly occurs on business weekdays with peek bike trips on tuesday, wednesday, and thursdays for Subscribers.The casual Customer have a small increase during the weekends.<jupyter_code>weekday_names = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
# create two rows of plotting surfaces
# and draw bar chart with occurrences of bike rides for each weekday

fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharey=True, sharex=True, figsize = (12, 9))

sns.countplot(x='weekday', 
              data=userstart[userstart.user_type == 'Customer'], 
              order=weekday_names, 
              color='orange', 
              saturation=0.7, 
              ax=ax1)
ax1.set(xlabel='', ylabel='Frequency', title='Customer weekday bike trips')

sns.countplot(x='weekday', 
                   data=userstart[userstart.user_type == 'Subscriber'], 
                   order=weekday_names, 
                   color='b', 
                   saturation=0.4, 
                   ax=ax2)
ax2.set(xlabel='', ylabel='Frequency', title='Subscriber weekday bike trips');
# bar chart of only Customer to better show the trend for weekends
fix, ax = plt.subplots(figsize=(12, 5))
sns.countplot(x='weekday', 
              data=userstart[userstart.user_type == 'Customer'], 
              order=weekday_names, 
              color='orange', 
              saturation=0.7, ax=ax)
ax.set(xlabel='', ylabel='Frequency', title='Customer weekday bike trips');<jupyter_output><empty_output><jupyter_text>3. Same station start and end bike tripsWhen looking at bike trips that start and end at the same station there is a interesting pattern that is revealed in the Customer user type. They have a higher number of these kind of trips than the regular Subscribers. I interpret this as it could be weekend tourists visiting the San Francisco Bay area and are doing more sightseeing kind of trips close to the hotel where they are staying. Than the commuting style usage pattern that the regular Subscribers have.<jupyter_code># filter stations that are same for both start and end
# introduce two new columns with weekday and part of day

# count occurrences of weekday partition over part of day
# and draw two bar charts for each one of the user type

def part_of_day(hour):
    if hour > 12:
        return 'Afternoon'
    else:
        return 'Morning'

same_station = bikeshare_df[bikeshare_df.start_station_id == bikeshare_df.end_station_id].copy()
same_station['weekday'] = same_station.start_time.dt.weekday_name
same_station['part_of_day'] = same_station.start_time.dt.hour.apply(part_of_day)

g = sns.catplot(x='weekday', 
            row='user_type', 
            hue='part_of_day', 
            data=same_station, 
            order=weekday_names,
            hue_order=['Morning', 'Afternoon'],
            kind='count', 
            aspect=2)

g.fig.suptitle('Bike ride that start and end at the same station', verticalalignment='bottom', fontsize=24)
g.set_axis_labels("", "Frequency")
(ax1, ax2) = g.axes.ravel()
ax1.set(title='Customer user type')
ax2.set(title='Subscriber user type');<jupyter_output><empty_output><jupyter_text>4. Bike rental hour of the dayThere is a distinct pattern with two spikes of bike rentals during the day.One in the morning at 8 o'clock and then later in the evening at 17 o'clock.This is a really good fit with a commuter pattern with people using bike rentals to travel to and from work.<jupyter_code># introduce new column with hour of start time
# count occurrences within each hour
# and draw a bar chart that is also saved to disk.

bikeshare_df['hour'] = bikeshare_df.start_time.dt.hour

g = sns.catplot(x='hour',
                data=bikeshare_df,
                kind='count',
                color='steelblue',
                aspect=2.3)

g.set(xlabel='Hour of the day', 
      ylabel='Totala number of bike trips', 
      title='Bike share starting hour of day')

ensure_dir(IMAGES_DIR)
plt.tight_layout()
plt.savefig(os.path.join(IMAGES_DIR, 'bike_rental_hour_of_day.jpg'));<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09712005984291236, 'fraction_numerical': 0.01259194614137888, 'mean_word_length': 4.468302658486707, 'pattern_counts': {'":': 1, '<': 28, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '363442', 'license': 'MIT', 'n_tokens_mistral': 2571, 'n_tokens_neox': 2397, 'n_words': 815, 'path': 'fordgobike-slide_deck.ipynb', 'repo_name': 'marcusholmgren/bikeshare-analysis', 'size': '8021'}