La plupart d'entre nous sont peut-être conscients des courbes de distribution normales, mais ceux qui sont nouveaux dans la distribution normale à chargement frontal et à chargement arrière, je voudrais fournir le contexte et ensuite continuer à énoncer mon problème.
Distribution à chargement frontal : Comme illustré ci-dessous, son démarrage est rapide. Par exemple dans un projet où plus de ressources sont supposées être consommées tôt dans le projet, le coût/heures est distribué de manière agressive au début du projet.
Distribution Back-Loaded : Contrairement à la distribution Front-Loaded, elle démarre avec une pente plus faible et de plus en plus raide vers la fin du projet. Par exemple lorsque la plupart des ressources sont supposées être consommées tard dans le projet.
Dans les graphiques ci-dessus, la ligne verte est la courbe S qui représente la distribution cumulative (utilisation des ressources sur la période proposée) et les colonnes bleues représentent la distribution isolée des ressources (coût/heures) au cours de cette période.
Pour référence, je fournis le graphique Courbe de Bell/distribution normale standard (lorsque Moyenne = Médiane) (ci-dessous) et la formule associée pour commencer.
Énoncé du problème : J'ai pu générer la courbe de distribution normale (voir ci-dessous avec les formules) mais je ne peux pas trouver de solution pour le chargement frontal ou le chargement arrière courbes.
Comment amener l'asymétrie vers la droite (distribution frontale/positivement asymétrique, ce qui signifie que la moyenne est supérieure à la médiane) et gauche asymétrique (distribution backloadée/asymétrique, ce qui signifie que la moyenne est inférieure à la médiane) dans une situation normale distribution?
Explication de la formule :
Cellule B8 désigne l'écart type choisi arbitrairement. Il affecte le kurtosis de la distribution normale. Dans la capture d'écran ci-dessus, je choisis la plage de la distribution normale de -3SD à 3SD.
Cellule B9 à B18 dénote la distribution paire de Z-Score en utilisant la formule:
=B8-((2*$B$8)/Period)
Cell C9 à C18 désigne la distribution normale sur la base du score Z et du montant en utilisant la formule:
=(NORMSDIST(B9)-NORMSDIST(B8))*Amount/(1-2*NORMSDIST($B$8))
Mise à jour: Suite à l'un des liens en commentaire, je me suis le plus rapproché de la situation ci-dessous. Le problème est surligné en jaune car en raison de l'utilisation de la fonction volatile Rand (), les graphiques ne sont pas lisses comme ils devraient l'être. Comme ma formule donnée ci-dessus ne crée pas de motif ZigZag, je suis sûr que nous pouvons avoir une distribution normale asymétrique et lisse aussi!
Remarque:
J'utilise Excel 2016, donc je me réjouis si une formule nouvellement introduite peut résoudre mon problème. Aussi, je n'hésite pas à utiliser des FDU.
Les nombres de répartition de la charge avant et de la charge arrière sont théoriques. Ils peuvent varier. Je ne suis intéressé que par la forme du graphique résultant.
Aide aimablement !
Vous pouvez générer la courbe à l'aide des méthodes ci-dessous et utiliser les nombres qu'ils génèrent pour votre besoin.
Avec des formules
La courbe
Remarques:
Pour copier passé
=A2+180/($G$3-1)
=RADIANS(A2)
=$G$4*SIN(B2 + SIN(B2)/2)
J'ai utilisé les formules mathématiques réelles pour arriver au résultat. Cela me semble ce que vous vouliez réaliser. Les cellules oranges dans la section "asymétrique" sont celles qui peuvent être modifiées pour faire varier le degré et la direction de l'inclinaison. Quelques images de démonstration sont ci-dessous, suivies des formules utilisées.
Formules à la ligne 5, colonne
B: =(A5*$A$2)+0
(0 est la moyenne, vous pouvez changer comme vous le souhaitez)
C: =(1/($A$2* SQRT(2*PI())))*EXP(-(B5^2)/2)
D: =0.5*(1+ERF(B5/SQRT(2)))
E: =$A$1*C5
F: =(A5*$A$2*(1+$F$2*SIN((F4*PI())/(2*$F$4))))+0
(0 est la moyenne, vous pouvez changer comme vous le souhaitez)
G: =(1/($A$2* SQRT(2*PI())))*EXP(-((F5+$G$2)^2)/2)
H: =0.5*(1+ERF((B5+$G$2)/SQRT(2)))
I: =$A$1*G5
Si vous voulez vous assurer que les bacs contiennent toujours une valeur, vous pouvez utiliser l'approche suivante, qui utilise des distributions normales et modifie simplement la moyenne et l'écart-type pour obtenir la courbe souhaitée.
La modification de la moyenne déplace le pic vers la gauche ou la droite. La modification de l'écart-type rend les quantités plus uniformes ou plus variables. J'ai utilisé 0-1000 comme plage par défaut dans l'exemple ci-dessous, mais il devrait être facile de modifier la formule pour apporter la valeur souhaitée. REMARQUE Afin de répondre à votre exigence selon laquelle tous les bacs doivent être différents de zéro, vous devez ajuster manuellement les nombres jusqu'à ce que vous obteniez une courbe qui convient.
Les cellules jaunes sont pour la saisie de données, les cellules vertes sont un décompte (donc si vous ajoutez des bacs, ils devraient être numérotés selon la séquence).
Formule dans la cellule B7 (copiée dans la cellule B16): =NORMDIST($A7*1000/MAX($A$6:$A$17),$B$3,$B$4,TRUE)-NORMDIST($A6*1000/MAX($A$6:$A$17),$B$3,$B$4,TRUE)
Formule dans la cellule C7 (copiée dans la cellule C16): =IF(A7=MAX($A$6:$A$17),$C$5-SUM(C$6:C6),ROUND(B7/SUM($B$7:$B$17)*$C$5,0))
L'ajout de nouveaux bacs est assez simple et est toujours basé sur une plage de 0 à 1 000, vous n'avez donc pas besoin de modifier d'autres chiffres que d'ajouter des lignes et de copier les formules:
L'exemple ci-dessus montre également comment un écart-type étroit et une moyenne élevée se combinent pour que les bacs de départ aient très peu de quantité. Mais il y a toujours une valeur (tant que le nombre est assez grand).
Vous voudrez peut-être prédéfinir les différentes sélections d'asymétrie si elles doivent être utilisées par d'autres personnes (rendre la colonne B dépendante d'une recherche, par exemple) mais j'espère que cela est suffisamment extensible pour vos besoins.
Basé sur les ans de @usmanhaq, macro vba faite pour la simulation de courbe de distribution. Corrigé pour une mise à l'échelle à 100% de la courbe avant et arrière. cliquez ici pour aller à Github Lib
Si vous êtes ouvert à un Python répondez au je peux vous donner le code pour obtenir Python Pandas libary pour générer le des observations aléatoires à partir d'un normal asymétrique, puis les regrouper (compartiment) pour vous. Ce qui suit dans un script Python qui capture le cas d'utilisation mais peut également être créé à l'aide de COM et donc créable à partir de VBA.
import numpy as np
import pandas as pd
from scipy.stats import skewnorm
class PythonSkewedNormal(object):
_reg_clsid_ = "{1583241D-27EA-4A01-ACFB-4905810F6B98}"
_reg_progid_= 'SciPyInVBA.PythonSkewedNormal'
_public_methods_ = ['GeneratePopulation','BinnedSkewedNormal']
def GeneratePopulation(self,a, sz):
# https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
np.random.seed(10);
#https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
return skewnorm.rvs(a, size=sz).tolist();
def BinnedSkewedNormal(self,a, sz, bins):
# https://docs.scipy.org/doc/numpy-1.15.1/reference/generated/numpy.random.seed.html
np.random.seed(10);
#https://docs.scipy.org/doc/scipy-0.19.1/reference/generated/scipy.stats.skewnorm.html
pop = skewnorm.rvs(a, size=sz); #.tolist();
bins2 = np.array(bins)
bins3 = pd.cut(pop,bins2)
table = pd.value_counts(bins3, sort=False)
table.index = table.index.astype(str)
return table.reset_index().values.tolist();
if __name__=='__main__':
print ("Registering COM server...")
import win32com.server.register
win32com.server.register.UseCommandLine(PythonSkewedNormal)
Et le code client VBA
Option Explicit
Sub TestPythonSkewedNormal()
Dim skewedNormal As Object
Set skewedNormal = CreateObject("SciPyInVBA.PythonSkewedNormal")
Dim lSize As Long
lSize = 100
Dim shtData As Excel.Worksheet
Set shtData = ThisWorkbook.Worksheets.Item("Sheet3") '<--- change sheet to your circumstances
shtData.Cells.Clear
Dim vBins
vBins = Array(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5)
'Stop
Dim vBinnedData
vBinnedData = skewedNormal.BinnedSkewedNormal(-5, lSize, vBins)
Dim rngData As Excel.Range
Set rngData = shtData.Cells(2, 1).Resize(UBound(vBins) - LBound(vBins), 2)
rngData.Value2 = vBinnedData
'Stop
End Sub
Exemple de sortie
(-5, -4] 0
(-4, -3] 0
(-3, -2] 4
(-2, -1] 32
(-1, 0] 57
(0, 1] 7
(1, 2] 0
(2, 3] 0
(3, 4] 0
(4, 5] 0
Code original déposé sur mon blog