Análise da Bay Area Bike Share

Introdução

Bay Area Bike Share é uma empresa que oferece aluguel de bicicletas on-demand para clientes em San Francisco, Redwood City, Palo Alto, Mountain View e San Jose. Os usuários podem desbloquear bicicletas de uma variedade de estações em cada cidade, e devolvê-las em qualquer estação dentro da mesma cidade. Os usuários pagam o serviço por meio de assinatura anual ou pela compra de passes de 3 dias ou 24 horas. Os usuários podem fazer um número ilimitado de viagens. Viagens com menos de trinta minutos de duração não têm custo adicional; Viagens mais longas incorrem em taxas de horas extras.

O projeto, visa colocar no lugar de um analista de dados realizando uma análise exploratória sobre os dados. Pondo em prática dois passos importantes: limpeza de dados e análise exploratória.

Data Wrangling (Limpeza de Dados)

In [1]:
# Importa todas as bibliotecas necessárias
%matplotlib inline
import csv
from datetime import datetime
import numpy as np
import pandas as pd
from babs_datacheck import question_3
from babs_visualizations import usage_stats, usage_plot
from IPython.display import display
import matplotlib.pyplot as plt
In [2]:
# definição dos arquivos
file_in  = '201402_trip_data.csv'
file_out = '201309_trip_data.csv'

with open(file_out, 'w') as f_out, open(file_in, 'r') as f_in:
    # configura o leitor de csv
    in_reader = csv.reader(f_in)
    out_writer = csv.writer(f_out)

    # escreve os dados no arquivo de saída até que a data limite seja atingida
    while True:
        datarow = next(in_reader)
        # data de início de das viagens na terceira coluna no formato 'm/d/yyyy HH:MM'
        if datarow[2][:9] == '10/1/2013':
            break
        out_writer.writerow(datarow)

Condensando os Dados de Viagem

In [3]:
sample_data = pd.read_csv('201309_trip_data.csv')

sample_data.head()
Out[3]:
Trip ID Duration Start Date Start Station Start Terminal End Date End Station End Terminal Bike # Subscription Type Zip Code
0 4576 63 8/29/2013 14:13 South Van Ness at Market 66 8/29/2013 14:14 South Van Ness at Market 66 520 Subscriber 94127
1 4607 70 8/29/2013 14:42 San Jose City Hall 10 8/29/2013 14:43 San Jose City Hall 10 661 Subscriber 95138
2 4130 71 8/29/2013 10:16 Mountain View City Hall 27 8/29/2013 10:17 Mountain View City Hall 27 48 Subscriber 97214
3 4251 77 8/29/2013 11:29 San Jose City Hall 10 8/29/2013 11:30 San Jose City Hall 10 26 Subscriber 95060
4 4299 83 8/29/2013 12:02 South Van Ness at Market 66 8/29/2013 12:04 Market at 10th 67 319 Subscriber 94103
In [4]:
# Mostra as primeiras linhas do arquivo de dados das estações
station_info = pd.read_csv('201402_station_data.csv')
station_info.head()
Out[4]:
station_id name lat long dockcount landmark installation
0 2 San Jose Diridon Caltrain Station 37.329732 -121.901782 27 San Jose 8/6/2013
1 3 San Jose Civic Center 37.330698 -121.888979 15 San Jose 8/5/2013
2 4 Santa Clara at Almaden 37.333988 -121.894902 11 San Jose 8/6/2013
3 5 Adobe on Almaden 37.331415 -121.893200 19 San Jose 8/5/2013
4 6 San Pedro Square 37.336721 -121.894074 15 San Jose 8/7/2013
In [5]:
def create_station_mapping(station_data):
    """
    Cria um mapeamento (tambémm conhecido como de-para) entre a estação 
    e a cidade
    """
    station_map = {}
    for data_file in station_data:
        with open(data_file, 'r') as f_in:
            
            weather_reader = csv.DictReader(f_in)
    
            for row in weather_reader:
                station_map[row['station_id']] = row['landmark'] 
    return station_map
In [6]:
def summarise_data(trip_in, station_data, trip_out):

    # gera o dicionário de mapeamento entre estações e cidades
    station_map = create_station_mapping(station_data)
    
    with open(trip_out, 'w') as f_out:
        # configura o objeto de escrita de csv       
        out_colnames = ['duration', 'start_date', 'start_year',
                        'start_month', 'start_hour', 'weekday',
                        'start_city', 'end_city', 'subscription_type']        
        trip_writer = csv.DictWriter(f_out, fieldnames = out_colnames)
        trip_writer.writeheader()
        
        for data_file in trip_in:
            with open(data_file, 'r') as f_in:
                # configura o leitor do csv
                trip_reader = csv.DictReader(f_in)

                # processa cada linha lendo uma a uma
                for row in trip_reader:
                    new_point = {}
                    
                    # converte a duração de segundos para minutos.
                    new_point['duration'] = int(row['Duration'])/60.0
                    
                    # reformate strings com datas para múltiplas colunas
                    trip_date = datetime.strptime(row['Start Date'], '%m/%d/%Y %H:%M')
                    new_point['start_date']  = trip_date.day
                    new_point['start_year']  = trip_date.year
                    new_point['start_month'] = trip_date.month
                    new_point['start_hour']  = trip_date.hour
                    new_point['weekday']     = trip_date.strftime("%A")
                    
                    # mapeia o terminal de inicio e fim com o a cidade de inicio e fim
                    new_point['start_city'] = station_map[row['Start Terminal']]
                    new_point['end_city']= station_map[row['End Terminal']]
                    
                    if 'Subscription Type' in row:
                        new_point['subscription_type'] = row['Subscription Type']
                    else:
                        new_point['subscription_type'] = row['Subscriber Type']

                    # escreve a informação processada para o arquivo de saída.
                    trip_writer.writerow(new_point)
## Verificando as contagem de dados
In [7]:
# processe os dados usando a função criada acima
station_data = ['201402_station_data.csv']
trip_in = ['201309_trip_data.csv']
trip_out = '201309_trip_summary.csv'
summarise_data(trip_in, station_data, trip_out)
In [8]:
# Carregue os dados novamente mostrando os dados
sample_data = pd.read_csv(trip_out)
display(sample_data.head())
duration start_date start_year start_month start_hour weekday start_city end_city subscription_type
0 1.050000 29 2013 8 14 Thursday San Francisco San Francisco Subscriber
1 1.166667 29 2013 8 14 Thursday San Jose San Jose Subscriber
2 1.183333 29 2013 8 10 Thursday Mountain View Mountain View Subscriber
3 1.283333 29 2013 8 11 Thursday San Jose San Jose Subscriber
4 1.383333 29 2013 8 12 Thursday San Francisco San Francisco Subscriber
In [9]:
question_3(sample_data)
Todas as contagens estão como esperadas.

Análise Exploratória de Dados

In [10]:
trip_data = pd.read_csv('201309_trip_summary.csv')
trip_data.head()
Out[10]:
duration start_date start_year start_month start_hour weekday start_city end_city subscription_type
0 1.050000 29 2013 8 14 Thursday San Francisco San Francisco Subscriber
1 1.166667 29 2013 8 14 Thursday San Jose San Jose Subscriber
2 1.183333 29 2013 8 10 Thursday Mountain View Mountain View Subscriber
3 1.283333 29 2013 8 11 Thursday San Jose San Jose Subscriber
4 1.383333 29 2013 8 12 Thursday San Francisco San Francisco Subscriber
In [11]:
print('Existem {:d} pontos no conjunto de dados'.format(trip_data.shape[0]))
print('A duração média das viagens foi de {:.2f} minutos'.format(trip_data['duration'].mean()))
print('A mediana das durações das viagens foi de {:.2f} minutos'.format(trip_data['duration'].median()))


duration_qtiles = trip_data['duration'].quantile([.25, .5, .75]).as_matrix()

print('25% das viagens foram mais curtas do que {:.2f} minutos'.format(duration_qtiles[0]))
print('25% das viagens foram mais compridas do que {:.2f} minutos'.format(duration_qtiles[2]))
Existem 27345 pontos no conjunto de dados
A duração média das viagens foi de 27.60 minutos
A mediana das durações das viagens foi de 10.72 minutos
25% das viagens foram mais curtas do que 6.82 minutos
25% das viagens foram mais compridas do que 17.28 minutos
In [12]:
usage_stats(trip_data)
Existem 27345 pontos no conjunto de dados
A duração média das viagens foi de 27.60 minutos
A mediana das durações das viagens foi de 10.72 minutos
25% das viagens foram mais curtas do que 6.82 minutos
25% das viagens foram mais compridas do que 17.28 minutos
Out[12]:
array([ 6.81666667, 10.71666667, 17.28333333])
In [49]:
# TODO: plote um gráfico de barras que mostre quantidade de viagens por subscription_type

subscription_type = trip_data.groupby('subscription_type')['subscription_type'].count()
plt.bar([1, 2], subscription_type, tick_label=['Customer', 'Subscriber'], color=['#ef6461', '#e4b363'])
plt.title('Quantidade de viagens X Tipo de Subscrição')
plt.ylabel('Quantidade de Viagens')
plt.xlabel('Tipo de Subscrição')
plt.show()
In [28]:
usage_plot(trip_data, 'subscription_type')
In [ ]:
# Gráfico baseado nas durações
In [30]:
trip_data['duration'].plot(kind='hist', color = ['#e4b363'])

plt.title('Viagens por Duração')
plt.ylabel('Viagens')
plt.xlabel('Duração')
plt.show()
In [ ]:
# Gráfico de barras para os dados com duração inferior a 60 minutos.
In [31]:
usage_plot(trip_data, 'duration', ['duration < 60'])
In [39]:
#usage_plot(trip_data, 'duration', ['duration < 60'], boundary = 0, bin_width = 5)

bins = np.arange(0, 60, 5)
search = trip_data.loc[trip_data['duration'] <= 60]
search['duration'].plot(kind='hist', bins = bins, color = ['#e4b363'])

plt.title('Viagens por Duração')
plt.ylabel('Viagens')
plt.xlabel('Duração')
plt.show()

Pequenos ajustes como este podem ser pequenos mas fazem toda a diferença na entrega de um trabalho de qualidade e com atenção aos detalhes.

Entre o intervalo de 5 a 10 há um maior número de viagens registradas

A cidade de San Francisco tem a maior quantidade de viagens com 8129 viagens registradas.

In [33]:
index = (search['duration'] >= 5) & (search['duration'] <= 10)
search[index].groupby( ['start_city', 'end_city']).size()
Out[33]:
start_city     end_city     
Mountain View  Mountain View     105
Palo Alto      Palo Alto          50
Redwood City   Redwood City       66
San Francisco  San Francisco    8129
San Jose       San Jose          675
dtype: int64
In [24]:
station_data = ['201402_station_data.csv',
                '201408_station_data.csv',
                '201508_station_data.csv' ]
trip_in = ['201402_trip_data.csv',
           '201408_trip_data.csv',
           '201508_trip_data.csv' ]
trip_out = 'babs_y1_y2_summary.csv'

# Esta função irá ler as informações das estações e das viagens
# e escreverá um arquivo processado com o nome trip_out
summarise_data(trip_in, station_data, trip_out)
In [25]:
trip_data = pd.read_csv('babs_y1_y2_summary.csv')
display(trip_data.head())
duration start_date start_year start_month start_hour weekday start_city end_city subscription_type
0 1.050000 29 2013 8 14 Thursday San Francisco San Francisco Subscriber
1 1.166667 29 2013 8 14 Thursday San Jose San Jose Subscriber
2 1.183333 29 2013 8 10 Thursday Mountain View Mountain View Subscriber
3 1.283333 29 2013 8 11 Thursday San Jose San Jose Subscriber
4 1.383333 29 2013 8 12 Thursday San Francisco San Francisco Subscriber
In [26]:
#Estatistica
usage_stats(trip_data)
Existem 669959 pontos no conjunto de dados
A duração média das viagens foi de 18.47 minutos
A mediana das durações das viagens foi de 8.62 minutos
25% das viagens foram mais curtas do que 5.73 minutos
25% das viagens foram mais compridas do que 12.58 minutos
Out[26]:
array([ 5.73333333,  8.61666667, 12.58333333])
In [27]:
#Explorando alguns gráficos

usage_plot(trip_data, 'start_year', ["subscription_type == 'Subscriber'"], n_bins = 3)
In [28]:
# Gráfico final 1
#weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
#name_dict = {i:day for i, day in enumerate(weekdays)}
#trip_data.groupby("weekday").count()["duration"].rename(name_dict).plot(kind="bar")
#plt.show()
#Através da dica para colcoar nome nos meses, refiz o gráfico final para mostrar o uso de viagens por dia da semana

trip_data['weekday'].value_counts().plot(kind = 'bar' , color = ['#e4b363'], figsize = (12, 6));

plt.title('Quantidade de viagens por Dia da Semana')
plt.xlabel('Dias da Semana')
plt.ylabel('Quantidade')
plt.show()

Nessa visão podemos desmistificar que o final de semana não é o dia com a maior quantidade de viagens registrada, sim a Quinta-Feira. Dessa forma pode-se otimizar a quantidade de bicicletas ou ações de reparos para o final de semana, já que possui um menor quantidade.

In [29]:
# Gráfico Final 2
search  = trip_data.groupby(['start_city','subscription_type'])['duration'].mean()
search.head(3)
search.plot(kind='bar', color=['#e4b363'], figsize=(12,6))

plt.title('Duração Média por Cidade e tipo de Assinantes')
plt.xlabel('Cidades por Tipo de Assinantes')
plt.ylabel('Duração Média')
plt.show()

Através desse gráfico pode-se observar que os Customers gastam mais tempo que os assinantes (Subscribers). Uma das razões que podemos levantar é que os assinantes cabam utilizando o serviço diariamente em viagens mais curtas. Além disso, nas cidades de Mountain View, Palo Alto e Redwood as viagens levam em média o dobro da duração que nas cidades de San Francisco e San Jose.