私たちのほとんどは正規分布曲線に気づいているかもしれませんが、フロントロードおよびバックロードの正規分布に不慣れな人は、背景を説明してから、問題の説明に進みます。
フロントロード配信:以下に示すように、すぐに開始します。たとえばプロジェクトの早い段階でより多くのリソースが消費されると想定されるプロジェクトでは、コスト/時間はプロジェクトの開始時に積極的に配分されます。
バックロード分布:フロントロード分布とは逆に、低い傾斜で始まり、プロジェクトの終わりに向かって急勾配になります。たとえばほとんどのリソースがプロジェクトの後半で消費されると想定された場合。
上記のグラフで、緑の線は累積分布(提案された時間におけるリソースの使用率)を表すSカーブで、青い列は分離された分布を表しますその期間のリソース(コスト/時間)の。
参考までに、ベルカーブ/標準正規分布(平均=中央値の場合)グラフ(下)と、最初に関連する数式を提供します。
問題ステートメント:正規分布曲線を生成することができましたが(式を使用して以下を参照)、フロントロードまたはバックロードのソリューションを見つけることができませんカーブ。
歪度を右(フロントロード/正に歪んだ分布、つまり平均が中央値よりも大きい)と左に歪める(バックロード/負に歪んだ分布、つまり平均が中央値よりも小さい)にする方法正規分布では?
式の説明:
セルB8は、任意に選択された標準偏差を示します。正規分布の尖度に影響を与えます。上のスクリーンショットでは、-3SDから3SDまでの正規分布の範囲を選択しています。
セルB9からB18は、次の式を使用してZスコアの偶数分布を示します。
=B8-((2*$B$8)/Period)
セルC9からC18は、次の式を使用して、Zスコアと量に基づく正規分布を示します。
=(NORMSDIST(B9)-NORMSDIST(B8))*Amount/(1-2*NORMSDIST($B$8))
更新:コメントのリンクの1つに従って、以下の状況に最も近づきました。揮発性のRand()関数の使用により、チャートは本来あるべきように滑らかではないため、問題は黄色のパターンで強調表示されています。上記の私の与えられた式はジグザグパターンを作成しないので、正規分布を歪め、平滑化することもできると確信しています!
注意:
私はExcel 2016を使用しているので、新しく導入された数式で問題を解決できるかどうかを歓迎します。また、私はUDFの使用をためらっていません。
フロントロードとバックロードの分配数は概念的なものです。それらは異なる場合があります。結果のグラフの形だけに興味があります。
親切に助けて!
実際の数式を使用して結果を得ました。私があなたが達成したかったように見えます。 「スキュー」セクションのオレンジ色のセルは、スキューの度合いと方向を変更するために変更できるセルです。デモ用のいくつかの写真を以下に示し、その後に使用した式を示します。
行5、列の数式
B:=(A5*$A$2)+0
(0は平均であり、好きなように変更できます)
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は平均であり、好きなように変更できます)
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
_
ビンに常に値が含まれていることを確認する場合は、正規分布を使用し、平均と標準偏差を変更するだけで、目的の曲線を得る次のアプローチを使用できます。
平均を変更すると、ピークが左または右に移動します。標準偏差を変更すると、数量がより均一になるか、より変動しやすくなります。以下の例では、デフォルトの範囲として0〜1000を使用していますが、数式を変更して必要な値を取得するのは簡単です。注すべてのビンがゼロ以外でなければならないという要件を満たすには、適合する曲線が得られるまで手動で数値を調整する必要があります。
黄色のセルはデータ入力用、緑のセルはカウントです(したがって、ビンを追加する場合は、シーケンスに従って番号を付ける必要があります)。
セルB7の数式(セル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)
セルC7の数式(セルC16にコピー):=IF(A7=MAX($A$6:$A$17),$C$5-SUM(C$6:C6),ROUND(B7/SUM($B$7:$B$17)*$C$5,0))
新しいビンを追加するのは非常に簡単で、まだ0〜1000の範囲に基づいているため、行を追加して数式をコピーする以外に、数値を変更する必要はありません。
上記の例は、狭い標準偏差と高い平均を組み合わせて、開始ビンの数量を非常に少なくする方法も示しています。しかし、まだ値があります(カウントが十分に大きい限り)。
これを他の人が使用する場合(たとえば、列Bをルックアップに依存させる)、さまざまな歪度の選択を事前に定義することをお勧めしますが、必要に応じてこれが十分に拡張可能であることを望みます。
@usmanhaqのansに基づいて、分布曲線シミュレーション用に作成されたvbaマクロ。フロントおよびバックローディング曲線の100%スケーリングを修正しました。 Github Libに移動するにはここをクリック
Python回答を受け入れる場合、私はコードを提供して、Python Pandasライブラリを生成することができます歪んだ法線からランダムに観察し、それらをビン(バケット)に変換します。Pythonスクリプト内の次のスクリプトは、ユースケースをキャプチャしますが、COMを使用して作成することもできるため、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)
そして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
出力例
(-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
元のコードは 私のブログ に寄託されました