Avant de modéliser dans des compétitions business ou d'analyse, nous avons permis de voir rapidement la corrélation entre les fonctionnalités créées et la variable objectif. Ici, en particulier, la modélisation est ciblée lorsque la variable objective telle que la prévision des ventes est une valeur continue.
Le code ci-dessous utilise les données de prévision de la demande de déjeuner de Signate. (Données: https://signate.jp/competitions/24/data)
Ces données sont la tâche de créer un modèle qui prédit le nombre de déjeuners vendus dans la colonne y.
colonne | Nom de l'en-tête | Type de données | La description |
---|---|---|---|
0 | datetid | datetime | Date à utiliser comme index (aaaa-m-d) |
1 | y | int | Nombre de ventes (variable objective) |
2 | week | char | Dimanche (du lundi au vendredi) |
3 | soldout | boolean | Drapeau épuisé (0:Pas en rupture de stock, 1:épuisé) |
4 | name | varchar | Menu principal |
5 | kcal | int | Il y a une carence en calories (kcal) dans le plat d'accompagnement |
6 | remarks | varchar | Remarques |
7 | event | varchar | Commencez à 13h00 Événement en interne où vous pouvez apporter votre propre déjeuner |
8 | payday | boolean | Drapeau de paie (1:Payday) |
9 | weather | varchar | Météo |
10 | precipitation | float | Précipitation. Si non"--" |
11 | temperature | float | Température |
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
df = pd.read_csv('./signate/train.csv')
# df.shape >> (207, 12)
df.head(2)
datetime | y | week | soldout | name | kcal | remarks | event | payday | weather | precipitation | temperature | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2013-11-18 | 90 | mois td> | 0 | Calmar tranché épais td> | NaN | NaN | NaN | NaN | Ensoleillé td> | -- | 19.8 |
1 | 2013-11-19 | 101 | Mar td> | 1 | Côtelette à nageoires artisanale td> | NaN | NaN | NaN | NaN | Ensoleillé td> | -- | 17.0 |
df['precipitation'] = df.precipitation.replace({'--' : '0'}).astype(float)
df = pd.get_dummies(df[['y', 'week', 'soldout', 'kcal', 'payday', 'weather', 'precipitation', 'temperature']])
df['payday'] = df.payday.fillna(0).astype(str)
df.head()
y | soldout | kcal | payday | precipitation | temperature | week_month th> | week_Thursday th> | week_Wed th> | week_mar th> | week_Fri th> | weather_fine weather th> | weather_sunny th> | weather_cloudy th> | weather_light nuageux th> | weather_rain th> | weather_snow th> | weather_Raiden th> | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 90 | 0 | NaN | 0.0 | 0.0 | 19.8 | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 101 | 1 | NaN | 0.0 | 0.0 | 17.0 | 0 | 0 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 118 | 0 | NaN | 0.0 | 0.0 | 15.5 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 120 | 1 | NaN | 0.0 | 0.0 | 15.2 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 130 | 1 | NaN | 0.0 | 0.0 | 16.1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
df.describe()
y | soldout | kcal | precipitation | temperature | week_month th> | week_Thursday th> | week_Wed th> | week_mar th> | week_Fri th> | weather_fine weather th> | weather_sunny th> | weather_cloudy th> | weather_light nuageux th> | weather_rain th> | weather_snow th> | weather_Raiden th> | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
count | 207.000000 | 207.000000 | 166.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 | 207.000000 |
mean | 86.623188 | 0.449275 | 404.409639 | 0.113527 | 19.252174 | 0.188406 | 0.207729 | 0.207729 | 0.198068 | 0.198068 | 0.256039 | 0.241546 | 0.256039 | 0.120773 | 0.115942 | 0.004831 | 0.004831 |
std | 32.882448 | 0.498626 | 29.884641 | 0.659443 | 8.611365 | 0.391984 | 0.406666 | 0.406666 | 0.399510 | 0.399510 | 0.437501 | 0.429058 | 0.437501 | 0.326653 | 0.320932 | 0.069505 | 0.069505 |
min | 29.000000 | 0.000000 | 315.000000 | 0.000000 | 1.200000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
25% | 57.000000 | 0.000000 | 386.000000 | 0.000000 | 11.550000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
50% | 78.000000 | 0.000000 | 408.500000 | 0.000000 | 19.800000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
75% | 113.000000 | 1.000000 | 426.000000 | 0.000000 | 26.100000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 0.000000 | 1.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
max | 171.000000 | 1.000000 | 462.000000 | 6.500000 | 34.600000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 | 1.000000 |
argument
--df: trame de données à visualiser --target: nom de colonne de la variable objectif
def make_plot(df, target):
plt_col = sorted([c for c in df.columns if c != target and len(df[c].unique()) > 1])
col_num = len(plt_col)
row_num = col_num // 2 + col_num % 2
col_num = 2
fig, ax = plt.subplots(row_num, col_num, figsize=(18, 3*row_num), sharex=False, sharey=False)
fig.subplots_adjust(left=0.1, right=0.95, hspace=0.7, wspace=0.4)
for i,col in enumerate(plt_col):
tmp = df[[target, col]]
tmp = tmp[~pd.isna(tmp[col])].reset_index(drop=True)
if len(tmp[col].unique()) == 1:
continue
p = ((i+1) // 2) + ((i+1) % 2) -1
q = abs(((i+1) % 2) - 1)
if len(tmp[col].unique()) > 2:
percentile095 = tmp[col].quantile(0.95)
over_tmp = tmp[tmp[col] >= percentile095].reset_index(drop=True)
over_tmp[col] = percentile095
if tmp[col].min() < 0:
percentile005 = tmp[col].quantile(0.05)
under_tmp = tmp[tmp[col] <= percentile005].reset_index(drop=True)
under_tmp[col] = percentile005
outof_percentile = tmp[(percentile005 < tmp[col]) & ( tmp[col] < percentile095)].reset_index(drop=True)
new_tmp = pd.concat([outof_percentile, under_tmp, over_tmp], axis=0)
if percentile095 == percentile005:
new_tmp = tmp.copy()
else:
percentile095 = tmp[col].quantile(0.95)
over_tmp = tmp[tmp[col] >= percentile095].reset_index(drop=True)
over_tmp[col] = percentile095
outof_percentile = tmp[tmp[col] < percentile095].reset_index(drop=True)
new_tmp = pd.concat([outof_percentile, over_tmp], axis=0)
if percentile095 == 0:
new_tmp = tmp.copy()
ax1 = ax[p,q]
ax2 = ax1.twinx()
n, bins, pathces = ax1.hist(new_tmp[col], bins='auto', label='Valeur de la fonctionnalité: {}'.format(col), ec='black')
new_tmp['bins'] = pd.cut(new_tmp[col], bins.tolist(), right=False).values.astype(str)
if len([f for f in new_tmp[col].unique() if bins[-2] <= f and f < bins[-1]]) > 0:
new_tmp['bins_start'] = [float(b.split(',')[0].replace('[', '')) for b in new_tmp['bins']]
bins_max = new_tmp['bins_start'].max()
nan_value = new_tmp.query('bins_start == @bins_max').bins.unique()[0]
new_tmp['bins'] = new_tmp['bins'].replace({'nan' : nan_value})
else:
new_tmp['bins'] = new_tmp['bins'].replace({'nan' : '[{}, {}]'.format(bins[-2], bins[-1])})
num_bin = new_tmp.groupby('bins').size().reset_index(name='cnt')
mean_target_bin = new_tmp.groupby('bins')[target].mean().reset_index().rename(columns={target : '{}_mean'.format(target)})
center_feature_bin = new_tmp.groupby('bins').agg({col : {np.max, np.min}}).reset_index()
center_feature_bin.columns = ['bins', 'feature_max', 'feature_min']
center_feature_bin['feature_center'] = center_feature_bin.apply(lambda x : (x['feature_max'] + x['feature_min']) / 2, axis=1)
plt_data = mean_target_bin.merge(center_feature_bin, on='bins', how='inner').merge(num_bin, on='bins', how='inner').sort_values('feature_center', ascending=True).reset_index(drop=True)
ax2.plot(plt_data['feature_center'], plt_data['{}_mean'.format(target)], label='Valeur moyenne de la variable objectif (pour chaque case)', marker='.', color='orange')
else:
new_tmp = tmp.copy()
ax1 = ax[p,q]
ax2 = ax1.twinx()
bins_list = sorted(new_tmp[col].unique().tolist())
a = new_tmp.groupby([col]).agg({col : len, target : np.mean}).rename(columns={col : 'count', target : '{}_mean'.format(target)}).reset_index().astype({col : str})
ax1.bar(a[col], a['count'], label='Valeur de la fonctionnalité: {}'.format(col), ec='black')
ax2.plot(a[col], a['{}_mean'.format(target)], label='Valeur moyenne de la variable objectif (pour chaque case)', marker='.', color='orange')
ax2.hlines([new_tmp[target].mean()], new_tmp[col].min(), new_tmp[col].max(), color="darkred", linestyles='dashed', label='Valeur moyenne de la variable objective (données complètes)')
handler1, label1 = ax1.get_legend_handles_labels()
handler2, label2 = ax2.get_legend_handles_labels()
ax1.legend(handler1 + handler2, label1 + label2, borderaxespad=0., bbox_to_anchor=(0, 1.45), loc='upper left', fontsize=9)
ax1.set_ylabel('count', fontsize=12)
ax2.set_ylabel('Variable objective', fontsize=12)
ax1.set_title('{}'.format(col), loc='right', fontsize=12)
plt.show()
target = 'y' #Spécification de la variable objectif
make_plot(df, target) #terrain
Éléments à visualiser ** 1. histogramme ou graphique à barres (bleu) **
—— Si la quantité d'entités est une valeur continue, un histogramme
** 2. Valeur moyenne de la variable objectif pour chaque case (jaune) **
--Graphe de ligne de rupture de la valeur moyenne de la variable objectif pour chaque bac (pour chaque valeur dans le cas de deux valeurs)
** 3. Valeur moyenne des variables objectives pour l'ensemble des données (rouge) **
Recommended Posts