はじめに
サプライ・チェイン・アナリティクスで最初に行うことは、需要データに対するABC分析である。 商品の需要量というのは、売れるものはたくさん売れるが、その数はごく少数であり、他のたくさんのそんなに売れない商品が山ほどあるという性質を持つ。 これをパレートの法則(全体の数値の大部分は、全体を構成するうちの一部の要素が生み出しているという理論。別名、80:20の法則、もう1つの別名、ばらつきの法則)と呼ぶ。
ここでは、仮想の企業の需要を生成し、それに対してABC分析を行う。 同時に、商品を売れている順に順位をつけ、順位の時系列的な変化を示すランク分析を提案する。
さらに、簡単な在庫分析を行う。これは、平均需要量や生産固定費用から、生産ロットサイズや安全在庫量を計算するものであり、 古典的な経済発注量モデルや安全在庫モデル(新聞売り子モデル)に基づくものである。
データの読み込み
まずは基本となるデータを読み込む。製品データはオプションであり、需要を売り上げや需要を重量や容量で評価したい場合に使う。 基本は、需要データ demand_df だけを使えば十分である。
需要データは以下の列をもつ.
date: 日付
cust: 顧客名
prod: 製品名
demand: 需要量
sales: 売上
需要量demandと売上の何れかに対して,ABC分析を行う.
prod_df = pd.read_csv(folder+ "prod.csv" ,index_col= 0 )
prod_df.head()
0
A
2
0
7
1
1
14
1
B
5
0
5
1
1
14
2
C
1
0
5
1
1
19
3
D
3
0
5
1
1
17
4
E
1
0
10
1
1
18
demand_df = pd.read_csv(folder+ "demand_with_promo_all.csv" ,index_col= 0 )
demand_df.head()
0
2019-01-01
札幌市
A
0
0
6
1
2019-01-01
札幌市
B
0
0
6
2
2019-01-01
札幌市
C
0
0
6
3
2019-01-01
札幌市
D
0
0
5
4
2019-01-01
札幌市
E
0
0
11
Kaggleデータの読み込み
以下で配布されているデータを読み込む.
https://www.kaggle.com/kyanyoga/sample-sales-data
Kaggleデータを用いたい場合には,以下を実行する. ただし,製品データがないので,製品関連の関数は適用できない.
kaggle_df = pd.read_csv(folder + "sales_data_sample.csv" , encoding= "latin" )
kaggle_df.head()
0
10107
30
95.70
2
2871.00
2/24/2003 0:00
Shipped
1
2
2003
...
897 Long Airport Avenue
NaN
NYC
NY
10022
USA
NaN
Yu
Kwai
Small
1
10121
34
81.35
5
2765.90
5/7/2003 0:00
Shipped
2
5
2003
...
59 rue de l'Abbaye
NaN
Reims
NaN
51100
France
EMEA
Henriot
Paul
Small
2
10134
41
94.74
2
3884.34
7/1/2003 0:00
Shipped
3
7
2003
...
27 rue du Colonel Pierre Avia
NaN
Paris
NaN
75508
France
EMEA
Da Cunha
Daniel
Medium
3
10145
45
83.26
6
3746.70
8/25/2003 0:00
Shipped
3
8
2003
...
78934 Hillside Dr.
NaN
Pasadena
CA
90003
USA
NaN
Young
Julie
Medium
4
10159
49
100.00
14
5205.27
10/10/2003 0:00
Shipped
4
10
2003
...
7734 Strong St.
NaN
San Francisco
CA
NaN
USA
NaN
Brown
Julie
Medium
5 rows × 25 columns
kaggle_df["date" ] = pd.to_datetime(kaggle_df.ORDERDATE)
kaggle_df.rename(columns= {"PRODUCTLINE" :"prod" , "CITY" :"cust" , "QUANTITYORDERED" :"demand" , "SALES" :"sales" }, inplace= True )
kaggle_demand_df = kaggle_df[["date" ,"cust" ,"prod" ,"demand" ,"sales" ]].copy()
kaggle_demand_df.head()
0
2003-02-24
NYC
Motorcycles
30
2871.00
1
2003-05-07
Reims
Motorcycles
34
2765.90
2
2003-07-01
Paris
Motorcycles
41
3884.34
3
2003-08-25
Pasadena
Motorcycles
45
3746.70
4
2003-10-10
San Francisco
Motorcycles
49
5205.27
需要と売り上げのtreemapを生成する関数 demand_tree_map
引数: - demand_df: 需要データフレーム(需要 demand と売り上げ sales の列を含む) - parent: 入れ子にする際の親項目; “cust” (既定値) もしくは “prod” を入れる. - value: 評価に使用する列名; 既定値は “demand” で, “sales” などを計算した列がデータフレーム内にあればそれを指定する.
返値: - Plotlyのtreemapオブジェクト
source
demand_tree_map
demand_tree_map (demand_df:pandas.core.frame.DataFrame,
parent:str='cust', value:str='demand')
需要と売り上げのtreemapを生成する関数
demand_tree_mapの使用例
sales列がない場合には,dataモジュールのdemand_attribute_compute関数を用いてsales(売り上げ)列を計算することができる。
需要のtreemapは,需要の大きさを面積とした階層図であり,売上は色で表現している.
fig = demand_tree_map(demand_df, parent = "prod" , value = "demand" );
#plotly.offline.plot(fig);
ABC分析とランク分析を行うための関数 abc_analysis
ABC分析のための関数を記述する、基本的には、需要データ demand_df だけあれば良いが、顧客や製品に関連した量を分析に加えたいときには、顧客データ cust_df や 製品データ prod_df も読み込んでおく。
古典的なABC分析では、3つのカテゴリーに製品や顧客を分類していたが、場合によっては4つに分類したい場合もあるだろう。 ここでは、より一般的にユーザーが与えた任意の数への分類を行う関数を準備する、カテゴリーに含まれる需要量を、ユーザーが与えた閾値をもとにして分類を行う。
引数:
demand_df: ABC分析を行うための需要データフレーム.列に集約を行うための列と値を格納した列が必要.
threshold: A,B,C の分類を行うための閾値.上位 threshold[0]の要素がAランク,次に上位の threshold[1]がBランク、と順に決めていく。 リストの長さは(アルファベットの数以下の)任意の正数であるが、合計が1以上になるような数値のリストとして与える.
agg_col: 集約を行う列名を文字列として与える.
value: A,B,Cの分類を行うための数値データを保管した列名を文字列として与える.
abc_name: 分類した結果を入れるための列名を文字列として与える.
rank_name: 数値データの順位を入れた列名を文字列として与える.
返値: 以下の3つのオブジェクトのタプル:
agg_df: agg_colによって集約したデータをvalueの数値の大きい順に並べたデータフレーム.abcとrankの情報が付加されている.
new_df: 元のデータフレームにabc_nameで与えた列にA(=0),B(=1),C(=2),…の分類を,rank_nameで与えた列にランク(順位)を入れている.
category: 0,1,2, …をキーとして与えると A,B,C,… ランクに属するデータ名(agg_colの要素)のリストを値として返す辞書.
source
abc_analysis
abc_analysis (demand_df:pandas.core.frame.DataFrame,
threshold:List[float], agg_col:str='prod',
value:str='demand', abc_name:str='abc',
rank_name:str='rank')
ABC分析のための関数
顧客・製品の組に対するABC分析 abc_analysis_all
顧客・製品ごとに需要予測を行う際に,予測しなくても良い組を予め抜き出しておくことが重要になる.そのため,顧客・製品の組に対してABC分析とランク分析を行う関数を準備しておく.
引数:
demand_df: ABC分析を行うための需要データフレーム.列に集約を行うための列と値を格納した列が必要.
threshold: A,B,C の分類を行うための閾値.上位 threshold[0]の要素がAランク,次に上位の threshold[1]がBランク、と順に決めていく。
返値: 以下の3つのオブジェクトのタプル:
agg_df: 顧客・製品によって集約したデータをdemandの数値の合計(sum)の大きい順に並べたデータフレーム. abcとrankと需要の標準偏差 (std) の情報が付加されている.
category: 0,1,2, …をキーとして与えると A,B,C,… ランクに属するデータ名(agg_colの要素)のリストを値として返す辞書.
source
abc_analysis_all
abc_analysis_all (deamnd_df:pandas.core.frame.DataFrame,
threshold:List[float])
abc_analysis(_all)関数の使用例
以下では、製品と顧客に対してABC分析を行い、得られた3種類のデータフレーム(元のデータフレームに列を追加したもの:new_df、製品データフレームagg_df_prod、顧客データフレーム:agg_df_cust)を示す。
確認用の小規模例
製品を需要量を元に3つのクラスに、閾値[0.4, 0.5, 0.1]を用いて分類
顧客を需要量を元に4つのクラスに、閾値[0.4, 0.3, 0.3, 0.1]を用いて分類
顧客・製品を元に4つのクラスに、閾値[0.4, 0.3, 0.3, 0.1]を用いて分類
df = pd.DataFrame({"prod" :[1 ,2 ,3 ,4 ,5 ], "demand" : [10 ,30 ,40 ,50 ,80 ]})
threshold = [0.4 , 0.5 , 0.2 ]
agg_df, new_df, category = abc_analysis(df, threshold, "prod" , "demand" , "abc" , "rank" )
print (category)
new_df
{0: ['5', '4'], 1: ['3', '2'], 2: ['1']}
0
1
10
C
4
1
2
30
B
3
2
3
40
B
2
3
4
50
A
1
4
5
80
A
0
demand_df = pd.read_csv(folder+ "demand_with_promo_all.csv" ,index_col= 0 )
threshold = [0.4 , 0.5 , 0.1 ]
agg_df, new_df, category = abc_analysis(demand_df = demand_df, threshold= threshold,
agg_col= "prod" , value= "demand" , abc_name= "abc" , rank_name= "rank" )
print (category)
new_df.head()
{0: ['E', 'J', 'H'], 1: ['A', 'B', 'G', 'F', 'C', 'D'], 2: ['I']}
0
2019-01-01
札幌市
A
0
0
6
B
3
1
2019-01-01
札幌市
B
0
0
6
B
4
2
2019-01-01
札幌市
C
0
0
6
B
7
3
2019-01-01
札幌市
D
0
0
5
B
8
4
2019-01-01
札幌市
E
0
0
11
A
0
agg_df_cust, new_df, category_cust = abc_analysis(
demand_df, [0.4 , 0.3 , 0.3 , 0.1 ], 'cust' , 'demand' , "customer_ABC" , "customer_rank" )
new_df.head()
0
2019-01-01
札幌市
A
0
0
6
C
27
1
2019-01-01
札幌市
B
0
0
6
C
27
2
2019-01-01
札幌市
C
0
0
6
C
27
3
2019-01-01
札幌市
D
0
0
5
C
27
4
2019-01-01
札幌市
E
0
0
11
C
27
0
2019-01-01
札幌市
A
0
0
6
1
2019-01-01
札幌市
B
0
0
6
2
2019-01-01
札幌市
C
0
0
6
3
2019-01-01
札幌市
D
0
0
5
4
2019-01-01
札幌市
E
0
0
11
...
...
...
...
...
...
...
343095
2020-12-30
那覇市
F
1
1
12
343096
2020-12-30
那覇市
G
1
1
12
343097
2020-12-30
那覇市
H
1
1
16
343098
2020-12-30
那覇市
I
1
1
10
343099
2020-12-30
那覇市
J
1
1
18
343100 rows × 6 columns
cust
佐賀市
566776
0
A
静岡市
308021
1
A
岡山市
257539
2
A
那覇市
158134
3
A
京都市
149615
4
A
agg_df,category = abc_analysis_all(demand_df, threshold= [0.4 , 0.3 , 0.3 , 0.1 ])
#print(category)
agg_df.head()
cust
prod
佐賀市
E
87858
59.304760
0
A
J
73705
49.763944
1
A
H
63240
40.927453
2
A
A
54031
38.126906
3
A
B
52751
35.582571
4
A
元のデータフレームにabcとrankとdemandを追加する関数 add_abc
引数: - df: 製品や顧客のデータフレーム;これにABC分析の結果を追加する. - agg_df: 集約した需要(もしくは売上),ABC分類,ランクを保管したデータフレーム;インデックスは製品(prod)もしくは顧客 (cust) - col_name: 追加したいデータの列名;製品の場合にはprod(既定値),顧客の場合にはcust - value: 追加したい列名;既定値は “demand”
返値: - df: ランク,ABC分類,集約した需要量を追加したデータフレーム
source
add_abc
add_abc (df:pandas.core.frame.DataFrame,
agg_df:pandas.core.frame.DataFrame, col_name:str='prod',
value:str='demand')
add_abc関数の使用例
cust_df = pd.read_csv(folder+ "cust.csv" , index_col= 0 )
new_cust_df = add_abc(df = cust_df, agg_df = agg_df_cust, col_name= "cust" , value= "demand" )
new_cust_df.head()
id
1
札幌市
43.06417
141.34694
48954
27
C
2
青森市
40.82444
140.74000
80974
13
B
3
盛岡市
39.70361
141.15250
35997
43
C
4
仙台市
38.26889
140.87194
43341
32
C
5
秋田市
39.71861
140.10250
39103
38
C
ABC別に色分けした需要のtreemapを生成する関数
引数: - demand_df: ABC分析の結果の列を含む需要データフレーム - abc_col: ABC分析の結果の列名
返値: - Plotlyのtreemapオブジェクト
source
demand_tree_map_with_abc
demand_tree_map_with_abc (demand_df:pandas.core.frame.DataFrame,
abc_col:str)
ABC別に色分けした需要のtreemapを生成する関数
demand_tree_map_with_abc関数の使用例
agg_df_cust, new_df, category_cust = abc_analysis(
demand_df, [0.4 , 0.3 , 0.3 , 0.1 ], 'cust' , 'demand' , "customer_ABC" , "customer_rank" )
fig = demand_tree_map_with_abc(new_df, abc_col= "customer_ABC" )
#plotly.offline.plot(fig);
ランク分析のための関数 rank_analysis と rank_analysis_all_periods
全ての期に対するランク分析を行う関数 rank_analysis と、期ごと(集約する単位は文字列で与える)のランク分析を行う関数 rank_analysis_all_periodsを記述する。
引数:
df: ランク分析を行う対象の需要データフレーム.列に集約を行うための列と,値を格納した列が必要.
agg_col: 集約を行う列名を文字列として与える.
value: ランクを計算するための数値データを保管した列名を文字列として与える.
agg_period (rank_analysis_all_periodsの場合のみ) : 集約を行う期間を “1m”(月次)のような文字列で与える.
返値:
名前を入れるとランク(rank_analysisの場合)もしくランクの期別リスト(rank_analysis_all_periodsの場合)を返す辞書
source
rank_analysis
rank_analysis (df:pandas.core.frame.DataFrame, agg_col:str, value:str)
全期間分のランク分析のための関数
source
rank_analysis_all_periods
rank_analysis_all_periods (df:pandas.core.frame.DataFrame, agg_col:str,
value:str, agg_period:str)
期別のランク分析のための関数
ランク分析の関数の使用例
全期間分の顧客需要のランク分析と、3ヶ月を1期とした各期間に対する製品のランク分析。
dic = rank_analysis(df= demand_df, agg_col= 'cust' , value= 'demand' ) #全ての期間に対する顧客需要量のランク分析
dic.popitem()
dic = rank_analysis_all_periods(df = demand_df, agg_col= 'prod' , value= 'demand' , agg_period= "1d" )
ランク分析の可視化関数 show_rank_analysis
ランクの時系列的な変化を表す図を生成するための関数。
引数:
demand_df: ランク分析を行う対象の需要データフレーム.列に集約を行うための列と,値を格納した列が必要
agg_df_prod: 製品のすべての期間に対するランクが保管されているデータフレーム;与えられない場合(引数がNoneの場合)には,abc_analysis関数で再計算する.
value: 分析をするデータが入っている列名(既定値は”demand”)
agg_period: 集約を行う期間を “1m”(月次)のような文字列で与える.
top_rank: 上位 top_rank 個のものだけを表示する
返値:
source
show_rank_analysis
show_rank_analysis (demand_df:pandas.core.frame.DataFrame,
agg_df_prod:pandas.core.frame.DataFrame=None,
value:str='demand', agg_period:str='1m',
top_rank:int=1)
ランク分析の可視化関数
show_rank_analysis関数の使用例
fig = show_rank_analysis(demand_df, value= "demand" , agg_period = "1d" , top_rank = 10 )
#plotly.offline.plot(fig);
リスク共同管理分析 risk_pooling_analysis
在庫をサプライ・チェインの上流(供給側)でもつか、下流(需要側)でもつかは、複数の需要地点(顧客)における需要の相関で決まる。 一般には、上流で在庫を共有することによって在庫の削減ができる。これをリスク共同管理 (risk pooling) とよぶ。
ここでは、製品ごとに、顧客の需要の標準偏差とリスク共同管理した場合の標準偏差の差を計算する。 また、それを需要の総量で割った比率(削減率)も計算する。 これは、標準偏差を平均値で割ることによる無次元の指標(変動係数: coefficient of variation: CV)に相当するものである。
この値が大きい製品ほど、リスク共同管理の効果が大きいので、サプライ・チェインの上流で在庫を保持した方が良いことになり、 逆に小さい製品ほど、下流で在庫を保持した方が良いことになる。
引数: - demand_df: 需要のデータフレーム - agg_period: 標準偏差を計算する際に用いる需要の集約を行う期(規定値は週)
返値: - inv_reduction_df : 標準偏差とその差と削減率を製品ごとに計算したデータフレーム; Rank列は製品の順位
source
risk_pooling_analysis
risk_pooling_analysis (demand_df:pandas.core.frame.DataFrame,
agg_period='1w')
リスク共同管理の効果を見るための関数
在庫を顧客側においた場合と、倉庫側においた場合の差を、標準偏差を計算することによって推定する。
risk_pooling_analysis関数の使用例
1週間を単位とした標準偏差をもとに、在庫を倉庫に置いた場合と工場に置いた場合の差を計算し、それを需要の総量で除した削減率(ReductionRatioの列)を計算する。 Plotlyによる可視化では、削減率の大きいものから棒グラフで表示し、需要の大きさのランクで色分けをする。
inv_reduction_df = risk_pooling_analysis(demand_df, agg_period= "1w" )
inv_reduction_df.head()
0
10
I
1137.883708
1138.748290
0.864583
1
8
C
1120.054537
1120.794951
0.740414
2
9
D
1114.387806
1115.096672
0.708866
3
4
A
1363.027889
1363.691051
0.663161
4
7
F
1282.927125
1283.552063
0.624938
在庫削減量の可視化関数 show_inventory_reduction
source
show_inventory_reduction
show_inventory_reduction (inv_reduction_df:pandas.core.frame.DataFrame)
在庫削減量の可視化関数
fig = show_inventory_reduction(inv_reduction_df)
#plotly.offline.plot(fig);
需要の製品ごとの平均と変動係数の可視化関数 show_mean_cv
需要を製品ごとに集約し,横軸に平均,縦軸に変動係数(\(CV=\sigma/\mu\) )の対数をとった散布図を生成する.
平均が大きく,変動係数が小さい製品は安定しているので倉庫(サプライ・チェインの下流)で保管し,平均が小さく変動係数が大きい製品は,工場(サプライ・チェインの上流)で 保管し,適宜顧客側に流す戦略が望ましい. また,平均が小さく,変動係数も小さい製品に対しては,さらに利益によって細分化したサプライ・チェイン戦略をとる必要がある. 利益の大きい製品は在庫費用も大きいので,サプライ・チェインの上流(工場側)で管理し,必要に応じて下流に流し, 利益の小さい製品は下流(倉庫側)で保管する.
製品ごとに同一のサプライ・チェイン戦略をとるのではなく,減り張りをつけて改善することによって,応答性(顧客サービス)と効率性を高めることができる.
引数: - demand_df: 需要データフレーム - prod_df: 製品データフレーム(オプション); 製品の在庫費用 (cust_calue) を表示するために用いる. - show_name: Trueのとき製品名も描画する.
返値: - fig: Plotlyの図オブジェクト
source
show_mean_cv
show_mean_cv (demand_df:pandas.core.frame.DataFrame,
prod_df:Optional[pandas.core.frame.DataFrame]=None,
show_name:bool=True)
show_mean_cv関数の使用例
fig = show_mean_cv(demand_df, prod_df, show_name= True )
#plotly.offline.plot(fig);
安全在庫、ロットサイズ、目標在庫(基在庫レベル)の設定関数 inventory_analysis
全ての需要が1つの工場で生産していると仮定したとき、その生産ロットサイズや安全在庫量は、古典的な経済発注量モデルと新聞売り子モデルで計算できる。
安全在庫量: 安全在庫係数 \(z\) , リード時間 \(L\) , 需要の標準偏差 \(\sigma\) としたとき \(z\sqrt{LT}\sigma\)
経済発注量(生産ロットサイズ): 生産固定費用 \(FC\) 、需要の平均値 \(d\) 、在庫費用 \(h\) としたとき \(\sqrt{2 FCd/h}\)
保管費率(無次元): \(r\) は以下の量の和とする。
利子率(投資額利率)
保険料率: 製品の種類および企業の方針によっても異なる.
消耗費率および陳腐化率: 製品の腐敗,破損,目減りなどを考慮して計算
税率: 在庫に課せられる法的な税率(日本では0)
在庫費用: \(h\) は、保管費率 \(r\) に製品の価値(製品データのplnt_value列)を乗じたものを週あたりに換算したもの
目標在庫量 \(=\) 基在庫レベル: 安全在庫量 \(+\) リード時間内の需要量
初期在庫量 \(=\) 目標在庫量に生産ロットサイズの半分を加えた量
引数:
prod_df: 製品データフレーム
demand_df: 多期間の製品別需要データフレーム
inv_reduction_df : 標準偏差とその差と削減率を製品ごとに計算したデータフレーム
z: 安全在庫係数
LT: リード時間
r: 年間保管費率
num_days: 標準偏差を計算する際の日数(既定値は \(7\) )
返値: 以下の列情報を加えた製品データフレーム prod_df
average_demand: num_days間の平均需要
standard_deviation: 需要の標準偏差
inv_cost: 在庫費用 $h = r $ plnt_value を1週間に換算したもの
lot_size: 最適発注量
safety_inventory: 安全在庫量
target_inventory: 目標在庫量(基在庫レベル); \(d LT + z\sqrt{LT}\sigma\)
initial_inventory: 初期在庫量
source
inventory_analysis
inventory_analysis (prod_df:pandas.core.frame.DataFrame,
demand_df:pandas.core.frame.DataFrame,
inv_reduction_df:pandas.core.frame.DataFrame,
z:float=1.65, LT:int=1, r:float=0.3, num_days:int=7)
工場における安全在庫量の計算
工場を1箇所に集約したと仮定する。複数工場の場合には、顧客と工場の紐付け情報が必要になる。
inventory_analysis関数の使用例
1週間を基本単位として、在庫量削減データフレームを計算し、それをもとに工場での在庫量を求める。
prod_df = pd.read_csv(folder+ "prod.csv" ,index_col= 0 )
inv_reduction_df = risk_pooling_analysis(demand_df, agg_period= "1w" )
new_prod_df = inventory_analysis(prod_df, demand_df, inv_reduction_df, z = 1.65 , LT = 1 , r = 0.3 , num_days= 7 )
#prod_df2.to_csv(folder + "prod_with_inventory.csv")
new_prod_df.head()
index
0
A
2
0
7
1
1
14
3598.172840
1363.027889
0.005753
4184.627560
2248.996017
5847.168857
5171.996017
1
B
5
0
5
1
1
14
3534.347051
1322.720355
0.005753
4147.347222
2182.488585
5716.835636
5040.488585
2
C
1
0
5
1
1
19
3179.353909
1120.054537
0.005753
4582.453009
1848.089986
5027.443895
4361.089986
3
D
3
0
5
1
1
17
2935.995885
1114.387806
0.005753
4165.373643
1838.739880
4774.735764
4225.739880
4
E
1
0
10
1
1
18
6132.412894
2192.456416
0.005753
6194.463943
3617.553086
9749.965980
8491.553086
生産・在庫シミュレーション inventory_simulation
上で生成したデータを用いて、シミュレーションを行う。生産は、安全在庫量を下回ったときに行われ、目標在庫量になるように生産量を決める。
TODO: NumPyで高速化, 様々な発注方策に対応
引数:
prod_df: 製品データ
demand_df: 需要データ
返値:
キーを製品名、値を、需要 demand、在庫 inventory、生産量 production を列とした時系列データフレームとした辞書
source
inventory_simulation
inventory_simulation (prod_df:pandas.core.frame.DataFrame,
demand_df:pandas.core.frame.DataFrame)
(Q,R)方策のシミュレーション
inventory_simulation関数の使用例
製品 A に対する需要、在庫、生産量を表すデータフレームを表示する。
production_df = inventory_simulation(new_prod_df, demand_df)
production_df[prod_df.name[0 ]].head()
2019-01-01
475
4696.996017
0.0
2019-01-02
688
4008.996017
0.0
2019-01-03
555
3453.996017
0.0
2019-01-04
449
3004.996017
0.0
2019-01-05
607
2397.996017
0.0
生産、在庫、需要の可視化関数 show_prod_inv_demand
引数:
prod_name: 製品名
production_df: 累積需要量、在庫量、生産量の列をもつデータフレーム
scale: 時間の集約を表す文字列。たとえば1日ごとに表示する場合には “1d” とする。
返値:
source
show_prod_inv_demand
show_prod_inv_demand (prod_name:str,
production_df:pandas.core.frame.DataFrame,
scale:str='1d')
生産、在庫、需要の可視化関数
show_prod_inv_demand関数の使用例
fig = show_prod_inv_demand(prod_df.name[3 ], production_df, scale= "1d" )
#plotly.offline.plot(fig);
需要量の可視化関数
source
plot_demands
plot_demands (prod_cust_list:List[str],
demand_df:pandas.core.frame.DataFrame, agg_period:str='1d')
需要の可視化関数
prod_cust_list = ["A,さいたま市" ,"B,さいたま市" , "E,佐賀市" ]
fig = plot_demands(prod_cust_list, demand_df, agg_period= "2w" )
基本分析クラス Scbas
上の関数を元にクラスを作る.
source
Scbas
Scbas (demand_df:pandas.core.frame.DataFrame,
agg_df_prod:Optional[pandas.core.frame.DataFrame]=None,
agg_df_cust:Optional[pandas.core.frame.DataFrame]=None,
new_demand_df:Optional[pandas.core.frame.DataFrame]=None,
reduction_df:Optional[pandas.core.frame.DataFrame]=None,
new_prod_df:Optional[pandas.core.frame.DataFrame]=None,
category_prod:Optional[Dict[int,List[str]]]=None,
category_cust:Optional[Dict[int,List[str]]]=None,
nodes:Optional[List[Dict]]=None, agg_period:str=('1w',))
Usage docs: https://docs.pydantic.dev/2.6/concepts/models/
A base class for creating Pydantic models.
Attributes: class_vars : The names of classvars defined on the model. private_attributes : Metadata about the private attributes of the model. signature : The signature for instantiating the model.
__pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
__pydantic_core_schema__: The pydantic-core schema used to build the SchemaValidator and SchemaSerializer.
__pydantic_custom_init__: Whether the model has a custom `__init__` function.
__pydantic_decorators__: Metadata containing the decorators defined on the model.
This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.
__pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to
__args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.
__pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
__pydantic_post_init__: The name of the post-init method for the model, if defined.
__pydantic_root_model__: Whether the model is a `RootModel`.
__pydantic_serializer__: The pydantic-core SchemaSerializer used to dump instances of the model.
__pydantic_validator__: The pydantic-core SchemaValidator used to validate instances of the model.
__pydantic_extra__: An instance attribute with the values of extra fields from validation when
`model_config['extra'] == 'allow'`.
__pydantic_fields_set__: An instance attribute with the names of fields explicitly set.
__pydantic_private__: Instance attribute with the values of private attributes set on the model instance.
scbas = Scbas(demand_df= demand_df, agg_period= "1w" )
fig = scbas.demand_tree_map(parent = "prod" , value = "demand" )
#plotly.offline.plot(fig);
fig_prod, fig_cust, agg_df_prod, agg_df_cust, new_df, category_prod, category_cust = scbas.generate_figures_for_abc_analysis(
value= "demand" , cumsum = False , cust_thres= "0.7, 0.2, 0.1" , prod_thres= "0.7, 0.2, 0.1"
)
#plotly.offline.plot(fig_cust);
#scbas.nodes
fig = scbas.show_rank_analysis(value= "demand" , top_rank = 10 )
#plotly.offline.plot(fig);
reduction_df = scbas.risk_pooling_analysis()
reduction_df.head()
0
10
I
1137.883708
1138.748290
0.864583
1
8
C
1120.054537
1120.794951
0.740414
2
9
D
1114.387806
1115.096672
0.708866
3
4
A
1363.027889
1363.691051
0.663161
4
7
F
1282.927125
1283.552063
0.624938
scbas = Scbas(demand_df= demand_df, agg_period= "1w" )
fig = scbas.show_mean_cv(prod_df= prod_df, show_name= True )
#plotly.offline.plot(fig);
scbas = Scbas(demand_df= demand_df, agg_period= "1w" )
prod_df = pd.read_csv(folder+ "prod.csv" ,index_col= 0 )
new_prod_df = scbas.inventory_analysis(prod_df, z = 1.65 , LT = 1 , r = 0.3 , num_days= 7 )
new_prod_df.head().T
name
A
B
C
D
E
weight
2
5
1
3
1
volume
0
0
0
0
0
cust_value
7
5
5
5
10
dc_value
1
1
1
1
1
plnt_value
1
1
1
1
1
fixed_cost
14
14
19
17
18
average_demand
3598.17284
3534.347051
3179.353909
2935.995885
6132.412894
standard_deviation
1363.027889
1322.720355
1120.054537
1114.387806
2192.456416
inv_cost
0.005753
0.005753
0.005753
0.005753
0.005753
lot_size
4184.62756
4147.347222
4582.453009
4165.373643
6194.463943
safety_inventory
2248.996017
2182.488585
1848.089986
1838.73988
3617.553086
target_inventory
5847.168857
5716.835636
5027.443895
4774.735764
9749.96598
initial_inventory
5171.996017
5040.488585
4361.089986
4225.73988
8491.553086