Hide keyboard shortcuts

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

# -*- coding: utf-8 -*- 

""" 

@file 

@brief Jeux de données artificiel lié à la prédiction de durées. 

""" 

from datetime import datetime, timedelta 

import pandas 

from numpy.random import randn, rand, gamma 

 

 

def duration_selling(date_begin=None, date_end=None, 

mean_per_day=10, sigma_per_day=5, 

week_pattern=None, 

hour_begin=9, hour_end=19, 

gamma_k=6., gamma_theta=0.25): 

""" 

Construit un jeu de données artificiel qui simule des paquets 

préparés par un magasin. Chaque paquet est préparé dès la réception 

d'une commande à une heure précise, il est ensuite stocké 

jusqu'à ce qu'un client viennent le chercher. 

 

@param date_begin première date 

@param date_end dernière date 

@param hour_begin heure d'ouverture du magasin 

@param hour_end heure de fermeture du magasin 

@param week_pattern tableau de 7 valeurs ou None 

pour une distribution uniforme sur les jours 

de la semaine 

@param mean_per_day nombre de paquets moyen par jour (suit une loi gaussienne) 

@param sigma_per_day écart type pour la loi gaussienne 

@param gamma_k paramètre *k* d'une loi gamma 

@param gamma_theta paramètre :math:`\\theta` d'une loi gamma 

@return jeu de données 

 

.. runpython:: 

:showcode: 

 

from papierstat.datasets.duration import duration_selling 

print(duration_selling().head()) 

 

Les commandes sont réparties de façon uniformes sur la journée 

même si c'est peu probable. La durée suit une loi :math:`\\Gamma`. 

Cette durée est ajoutée à l'heure où est passée la commande, 

les heures nocturnes et le week-end ne sont pas comptées. 

La durée ne peut excéder 10h. 

 

.. runpython:: 

:rst: 

 

from papierstat.datasets.documentation import list_notebooks_rst_links 

links = list_notebooks_rst_links('lectures', 'artificiel_duration') 

links = [' * %s' % s for s in links] 

print('\\n'.join(links)) 

""" 

if date_begin is None: 

date_begin = datetime.now() - timedelta(365, 1, 1) 

date_begin = datetime( 

date_begin.year, date_begin.month, date_begin.day) 

if date_end is None: 

date_end = datetime.now() 

date_end = datetime(date_end.year, date_end.month, date_end.day) 

if date_begin >= date_end: 

raise ValueError( 

"begin >= end {0} >= {1}".format(date_begin, date_end)) 

if week_pattern is None: 

week_pattern = [1.] * 5 + [0., 0.] 

 

gauss = randn(1000) 

pos_gauss = 0 

uni = rand(1000) 

pos_uni = 0 

gam = gamma(gamma_k, gamma_theta, 1000) 

pos_gam = 0 

add1d = timedelta(seconds=24 * 3600) - \ 

(timedelta(seconds=hour_end * 3600) - timedelta(seconds=hour_begin * 3600)) 

 

day_duration = (hour_end - hour_begin) * 3600 

date_begin += timedelta(seconds=hour_begin * 3600) 

 

rows = [] 

while date_begin <= date_end: 

wk = date_begin.weekday() 

nb = max(int(week_pattern[wk] * mean_per_day), 0) 

if nb == 0: 

date_begin += timedelta(days=1) 

continue 

nb += gauss[pos_gauss] * sigma_per_day # pylint: disable=E1136 

nb = int(max(nb, 0)) 

pos_gauss += 1 

if pos_gauss >= len(gauss): 

gauss = randn(1000) 

pos_gauss = 0 

if nb == 0: 

date_begin += timedelta(days=1) 

continue 

for _ in range(0, int(nb)): 

db = uni[pos_uni] * day_duration # pylint: disable=E1136 

pos_uni += 1 

if pos_uni >= len(uni): 

uni = rand(1000) 

pos_uni = 0 

 

g = min(gam[pos_gam] * 3600, 36000) # pylint: disable=E1136 

pos_gam += 1 

if pos_gam >= len(gam): 

gam = gamma(gamma_k, gamma_theta, 1000) 

pos_gam = 0 

 

rec = dict(commande=date_begin + timedelta(seconds=db)) 

rec['true_duration'] = g / 3600 

end = rec['commande'] + timedelta(seconds=g) 

if end.hour >= hour_end or end.hour < hour_begin: 

end += add1d 

while end.weekday() >= 5: 

end += timedelta(seconds=24 * 3600) 

rec["reception"] = end 

rows.append(rec) 

date_begin += timedelta(days=1) 

return pandas.DataFrame(rows)