<jupyter_start><jupyter_text>Preço Dinâmico de Frete na OLX Pay Union Squad – Let<NAME>, <NAME>, <NAME>, <NAME>Por meio de um mecanismo de economia do compartilhamento, criamos uma área dentro do app da OLX para que usuário possam ser entregadores independentes. Assim, é criado um mecanismo de remuneração para oferecer a facilidade do comprador não precisar se deslocar para coletar o item comprado. O código deste arquivo fornece um mecanismo de otimização da experiência do usuário e do empregador por meio da criação de um modelo estatístico de preço dinâmico do frete e do tempo de entrega por meio de uma conexão com a API do Bing Maps (produzida pela Microsoft). A solução apresentada também otimiza a logística reversa, pois o entregador autônomo também pode transportar produtos que precisem ser trocados ou retificados.Para fazermos as estimativas, utilizamos uma base de dados pública sobre vendas de ecommerce no Brasil, disponibilizada pela Olist e armazenada no Kaggle. Os dados, bem como uma descrição detalhada dos mesmos, podem ser acessados neste link: https://www.kaggle.com/olistbr/brazilian-ecommerce  Importando bibliotecas e fazendo ajustes visuais<jupyter_code>import pandas as pd
import numpy as np
import seaborn as sns
import palettable
import matplotlib.pyplot as plt
%matplotlib inline
from jupyterthemes import jtplot
jtplot.style(theme='monokai', context='notebook', ticks=True, grid=False)
for m,n in zip(["display.max_columns","display.max_rows"], [None,10]):
    pd.set_option(m,n)

import matplotlib.style
import matplotlib as mpl
for m,n in zip(['grid.color','axes.titlecolor','axes.labelcolor','xtick.color','ytick.color','axes.titlesize',
    'figure.figsize','legend.framealpha'],['white','white','white','white','white','20.0','13.0, 8.0','0.8']):
    mpl.rcParams[m] = n<jupyter_output><empty_output><jupyter_text>Importando os dados<jupyter_code>for i in ['customers','orders','order_items','sellers','products','geolocation']:
    globals()[str(i)] = pd.read_csv('/Users/pedrocerbino/Downloads/archive/olist_' + str(i) + '_dataset.csv')
geolocation.head().T[[0,1,2]]
orders.head().T[[0,1,2]]
order_items.head().T[[0,1,2]]
products.head().T[[0,1,2]]<jupyter_output><empty_output><jupyter_text>Realizamos uma aproximação do CEPO endereço exato não é divulgado por motivos de privacidade, mas os primeiros dígitos do CEP são suficientes para estimar a distância da entrega<jupyter_code>geolocation = geolocation.groupby('geolocation_zip_code_prefix',as_index=False).median()
geolocation.head().T[[0,1,2]]
for i in ['sellers','customers']:
    globals()[str(i)] = globals()[str(i)][[i[:-1]+'_zip_code_prefix',i[:-1]+'_id']].merge(geolocation[['geolocation_zip_code_prefix','geolocation_lat',
    'geolocation_lng']],left_on=i[:-1]+'_zip_code_prefix',right_on='geolocation_zip_code_prefix')
customers.head().T[[0,1,2]]
sellers.head().T[[0,1,2]]<jupyter_output><empty_output><jupyter_text>Agregamos todas as tabelas<jupyter_code>freight = order_items[['freight_value','order_id','product_id','seller_id']].merge(
            sellers[['seller_id','geolocation_lat','geolocation_lng']],on='seller_id').merge(
            orders[['order_id','customer_id']],on='order_id').merge(
            customers[['customer_id','geolocation_lat','geolocation_lng']],on='customer_id').merge(
            products[['product_id','product_weight_g','product_length_cm','product_height_cm',
            'product_width_cm']],on='product_id')
freight.drop(inplace=True,columns=['product_id','seller_id','customer_id'])<jupyter_output><empty_output><jupyter_text>Calculamos a distância geodésica e o volume do produto<jupyter_code>import geopy.distance
distance = []
for i,k,m,n in zip(freight.geolocation_lat_x,freight.geolocation_lng_x,freight.geolocation_lat_y,
                   freight.geolocation_lng_y):
    dist = geopy.distance.geodesic((i,k),(m,n))
    distance.append(dist.meters)
freight.insert(1,'distance',distance)
freight.distance = freight.distance/1000 # distancia aproximada em quilômetros
freight.insert(2,'volume',
               freight.product_length_cm*freight.product_height_cm*freight.product_width_cm)
freight<jupyter_output><empty_output><jupyter_text>Visualizamos os dados<jupyter_code>sns.heatmap(freight.corr())
plt.title('Matriz de Correlação');
plt.figure()
for k,j in zip([1,2,3,4],['freight_value','distance','volume','product_weight_g']):
    plt.subplot(2, 2, k)
    sns.distplot(freight[j],bins=10,color='purple',kde_kws={"color":"orange"})
    plt.title('Distribuição do '+j.title(), size=18)
    plt.xlabel('')
plt.tight_layout()<jupyter_output><empty_output><jupyter_text>Plotamos a relação entre os dados<jupyter_code>sns.regplot(x='distance',y='freight_value',data=freight,color='crimson')#volume,product_weight_g)
plt.title('Frete vs Distância');
sns.regplot(x='volume',y='freight_value',data=freight,color='orange')
plt.title('Frete vs Volume');
sns.regplot(x='product_weight_g',y='freight_value',data=freight,color='aqua')
plt.title('Frete vs Volume');<jupyter_output><empty_output><jupyter_text>Equacionamos o ModeloConsideramos que existe um valor mínimo de frete ($\alpha$) que é incrementado a partir de variáveis exógenas ponderadas pelos seus respectivos coeficientes ($\beta_i$). O resíduo representa as variáveis omitidas $Frete = \alpha + \beta_1\cdot Distancia + \beta_3\cdot Peso + \beta_2\cdot Volume + Residuo$  Em um cenário com mais dados, poderíamos desmembrar o resíduo em dados de trânsito previsto, previsões pluviométricas e limitação do número de entregadores<jupyter_code>import statsmodels.api as sm
X, y = freight[['product_weight_g','volume','distance']], freight.freight_value
X = sm.add_constant(X)
est = sm.OLS(y, X, missing='drop').fit()
est.summary()<jupyter_output><empty_output><jupyter_text>Pelo modelo, vemos que há uma explicação estatísticamente significante (p-valor menor que 0.05), conseguindo prever 55,5% do preço do frete (R-squared)  Estimando os parâmetros<jupyter_code>est.params<jupyter_output><empty_output><jupyter_text>$Frete = 7.362944 + 0.010601\cdot Distancia + 0.001659\cdot Peso + 0.000186\cdot Volume + Residuo$  Plotando Partial Regression<jupyter_code>fig = sm.graphics.plot_partregress_grid(est)
fig.tight_layout(pad=1.0)<jupyter_output><empty_output><jupyter_text>Plotando Fitted ValuesEm vermelho estão as observações incluídas no modelo. Em azul, as que não conseguiram ser previstas.<jupyter_code>fig = sm.graphics.plot_fit(est, 'distance')
fig.tight_layout(pad=1.0)
fig = sm.graphics.plot_fit(est, 'volume')
fig.tight_layout(pad=1.0)
fig = sm.graphics.plot_fit(est, 'product_weight_g')
fig.tight_layout(pad=1.0)<jupyter_output><empty_output><jupyter_text>Calculando o Tempo de EntregaUtilizaremos a API do Bing Maps que é open source e fornece estimativas de tempo de trajeto com base em previsões de trânsito e no padrão de velocidade do veículo escolhido (estimamos tempo de entrega para carros, visto que é um meio mais factível para entregas na economia colaborativa). Mais detalhes da API podem ser acessados aqui: https://docs.microsoft.com/en-us/bingmaps/rest-services/routes/calculate-a-distance-matrix<jupyter_code>c = 0
distance, duration = [], []
for i,k,m,n in zip(freight.geolocation_lat_x,freight.geolocation_lng_x,freight.geolocation_lat_y,
                   freight.geolocation_lng_y):
    k = pd.read_json('https://dev.virtualearth.net/REST/v1/Routes/DistanceMatrix?origins='+str(i)+
                     ','+str(k)+'&destinations='+str(m)+','+str(n)+'&travelMode=driving&key=<KEY>')
    duration.append(list(list(list(k['resourceSets'].values[0].values())[1][0].values())[4][0].values())[4]/60)
    c += 1
    print(c)
adj_freight = freight.copy()
adj_freight.insert(1,'duration',duration) # durancao em horas
adj_freight.drop(inplace=True,columns=['geolocation_lat_x','geolocation_lng_x','geolocation_lat_y',
                 'geolocation_lng_y','product_height_cm','product_length_cm','product_width_cm'])
adj_freight
sns.distplot(adj_freight['duration'],bins=10,color='purple',kde_kws={"color":"orange"})
plt.title('Distribuição do Tempo de Entrega', size=18)
plt.xlabel('');<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.13542688910696762, 'fraction_numerical': 0.01386162904808636, 'mean_word_length': 7.032512315270936, 'pattern_counts': {'":': 2, '<': 54, '<?xml version=': 0, '>': 54, 'https://': 3, 'lorem ipsum': 0, 'www.': 1, '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': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '547677', 'license': 'MIT', 'n_tokens_mistral': 3057, 'n_tokens_neox': 2946, 'n_words': 577, 'path': 'OLX Hackathon.ipynb', 'repo_name': 'danielnrocha/OLX_Hackathon', 'size': '8238'}