Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# -*- coding: utf-8 -*-
2"""
3@file
4@brief Jeux de données artificiel lié à la prédiction de durées.
5"""
6from datetime import datetime, timedelta
7import pandas
8from numpy.random import randn, rand, gamma
11def duration_selling(date_begin=None, date_end=None,
12 mean_per_day=10, sigma_per_day=5,
13 week_pattern=None,
14 hour_begin=9, hour_end=19,
15 gamma_k=6., gamma_theta=0.25):
16 """
17 Construit un jeu de données artificiel qui simule des paquets
18 préparés par un magasin. Chaque paquet est préparé dès la réception
19 d'une commande à une heure précise, il est ensuite stocké
20 jusqu'à ce qu'un client viennent le chercher.
22 @param date_begin première date
23 @param date_end dernière date
24 @param hour_begin heure d'ouverture du magasin
25 @param hour_end heure de fermeture du magasin
26 @param week_pattern tableau de 7 valeurs ou None
27 pour une distribution uniforme sur les jours
28 de la semaine
29 @param mean_per_day nombre de paquets moyen par jour (suit une loi gaussienne)
30 @param sigma_per_day écart type pour la loi gaussienne
31 @param gamma_k paramètre *k* d'une loi gamma
32 @param gamma_theta paramètre :math:`\\theta` d'une loi gamma
33 @return jeu de données
35 .. runpython::
36 :showcode:
38 from papierstat.datasets.duration import duration_selling
39 print(duration_selling().head())
41 Les commandes sont réparties de façon uniformes sur la journée
42 même si c'est peu probable. La durée suit une loi :math:`\\Gamma`.
43 Cette durée est ajoutée à l'heure où est passée la commande,
44 les heures nocturnes et le week-end ne sont pas comptées.
45 La durée ne peut excéder 10h.
47 .. runpython::
48 :rst:
50 from papierstat.datasets.documentation import list_notebooks_rst_links
51 links = list_notebooks_rst_links('lectures', 'artificiel_duration')
52 links = [' * %s' % s for s in links]
53 print('\\n'.join(links))
54 """
55 if date_begin is None:
56 date_begin = datetime.now() - timedelta(365, 1, 1)
57 date_begin = datetime(
58 date_begin.year, date_begin.month, date_begin.day)
59 if date_end is None:
60 date_end = datetime.now()
61 date_end = datetime(date_end.year, date_end.month, date_end.day)
62 if date_begin >= date_end:
63 raise ValueError( # pragma: no cover
64 "begin >= end {0} >= {1}".format(date_begin, date_end))
65 if week_pattern is None:
66 week_pattern = [1.] * 5 + [0., 0.]
68 gauss = randn(1000)
69 pos_gauss = 0
70 uni = rand(1000)
71 pos_uni = 0
72 gam = gamma(gamma_k, gamma_theta, 1000)
73 pos_gam = 0
74 add1d = timedelta(seconds=24 * 3600) - \
75 (timedelta(seconds=hour_end * 3600) - timedelta(seconds=hour_begin * 3600))
77 day_duration = (hour_end - hour_begin) * 3600
78 date_begin += timedelta(seconds=hour_begin * 3600)
80 rows = []
81 while date_begin <= date_end:
82 wk = date_begin.weekday()
83 nb = max(int(week_pattern[wk] * mean_per_day), 0)
84 if nb == 0:
85 date_begin += timedelta(days=1)
86 continue
87 nb += gauss[pos_gauss] * sigma_per_day # pylint: disable=E1136
88 nb = int(max(nb, 0))
89 pos_gauss += 1
90 if pos_gauss >= len(gauss):
91 gauss = randn(1000)
92 pos_gauss = 0
93 if nb == 0:
94 date_begin += timedelta(days=1)
95 continue
96 for _ in range(0, int(nb)):
97 db = uni[pos_uni] * day_duration # pylint: disable=E1136
98 pos_uni += 1
99 if pos_uni >= len(uni):
100 uni = rand(1000)
101 pos_uni = 0
103 g = min(gam[pos_gam] * 3600, 36000) # pylint: disable=E1136
104 pos_gam += 1
105 if pos_gam >= len(gam):
106 gam = gamma(gamma_k, gamma_theta, 1000)
107 pos_gam = 0
109 rec = dict(commande=date_begin + timedelta(seconds=db))
110 rec['true_duration'] = g / 3600
111 end = rec['commande'] + timedelta(seconds=g)
112 if end.hour >= hour_end or end.hour < hour_begin:
113 end += add1d
114 while end.weekday() >= 5:
115 end += timedelta(seconds=24 * 3600)
116 rec["reception"] = end
117 rows.append(rec)
118 date_begin += timedelta(days=1)
119 return pandas.DataFrame(rows)