Je voudrais implémenter la méthode FIFO en utilisant numpy. Plus précisément, j'ai un tableau numpy STOCK
qui ressemble à ceci
UPDATED_STOCK= array([ [5, 4, 5, ..., 6, 8, 1], # 6-1, 4, 5, ... BOOKED OUT=1 [0, 0, 1, ..., 2, 3, 5], # 1-1, 2-2, 5-4, ... BOOKED OUT=7 [4, 6, 3, ..., 5, 6, 7], # 7-3, 6, 3, ... BOOKED OUT=3 ..., [0, 1, 8, ..., 7, 6, 1], # 2-2, 5-4, 8, ... BOOKED OUT=6 [0, 2, 7, ..., 2, 8, 4], # 2-2, 8-6, 7, ... BOOKED OUT=8 [0, 0, 4, ..., 1, 1, 3]]) # 1-1, 2-2, 6-2, ... BOOKED OUT=5
, où chaque ligne représente une catégorie de produits différente et chaque colonne le nombre d'articles achetés à un endroit spécifique date.
Maintenant, j'ai un deuxième tableau SOLD
qui ressemble à ceci
SOLD = numpy.random.randint(1, 9, size=10_000) SOLD = array([1, 7, 3, ..., 6, 8, 5])
où chaque nombre représente le nombre de produits vendu par catégorie.
Je souhaite maintenant mettre à jour le tableau STOCK
en utilisant le Méthode FIFO . Cela signifie que je souhaite réserver les n premiers éléments cumulés par catégorie de produit. Dans le cas ci-dessus, la sortie devrait être quelque chose comme
import numpy numpy.random.seed(1) STOCK = numpy.random.randint(1, 9, size=(10_000, 10)) STOCK = array([ [6, 4, 5, ..., 6, 8, 1], [1, 2, 5, ..., 2, 3, 5], [7, 6, 3, ..., 5, 6, 7], ..., [2, 5, 8, ..., 7, 6, 1], [2, 8, 7, ..., 2, 8, 4], [1, 2, 6, ..., 1, 1, 3]])
Pourtant, je ne sais pas comment résoudre ce problème. Des idées?
3 Réponses :
J'espère que cela vous convient.
import numpy as np np.random.seed(1) STOCK = np.random.randint(1, 9, size=(10000, 10)) SOLD = np.random.randint(1, 9, size=10000) i = 0 while SOLD.sum() > 0: # The minimum between the ith column of STOCK and SOLD MIN = np.minimum(SOLD, STOCK[:, i]) STOCK[:, i] -= MIN SOLD -= MIN i += 1
Bien, ça devrait marcher! Mais pensez-vous que nous pouvons vectoriser ce problème? Je pense que cela pourrait être un peu lent ... surtout si nous augmentons le nombre de pas de temps de 10 à, disons, 1000.
En fait, il ne sera pas influencé par le nombre de colonne de STOCK
puisque l'algorithme s'arrête lorsque SOLD
est nul.
Une manière plus condensée, en utilisant cumsum
:
import numpy as np x = np.random.randint(1,10, size=(7, 5)) out = np.random.randint(1,10, size=(7, 1)) print(x, out) cum = x.cumsum(1) np.diff(np.hstack((np.zeros(x.shape[0])[:,None], np.clip(cum - out, 0, cum.max()))))
Essentiellement, vous faites une somme cumulative sur le tableau, retirez le out
, coupez à 0 et additionnez-le. Cela reproduira un processus de type FIFO. Cela fonctionne vectorisé.
Mise à jour: j'ai trouvé une solution assez rapide (similaire à celle de Mstaino)
%timeit book_out(STOCK.copy(), SOLD.copy()) > 1.13 ms ± 5.79 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
numpy.random.seed(1) STOCK = numpy.random.randint(1, 9, size=(10_000, 10)) SOLD = numpy.random.randint(1, 9, size=10_000) def book_out(stock, sold): booking_out = numpy.minimum(stock.cumsum(axis=1), sold[:,None]) booking_out[:,1:] -= booking_out[:,:-1] stock -= booking_out