# サプライ・チェイン基本分析システム SCBAS


<!-- WARNING: THIS FILE WAS AUTOGENERATED! DO NOT EDIT! -->

![](01abc_files/figure-commonmark/cell-3-output-1.jpeg)

## はじめに

サプライ・チェイン・アナリティクスで最初に行うことは、需要データに対するABC分析である。
商品の需要量というのは、売れるものはたくさん売れるが、その数はごく少数であり、他のたくさんのそんなに売れない商品が山ほどあるという性質を持つ。
これをパレートの法則（全体の数値の大部分は、全体を構成するうちの一部の要素が生み出しているという理論。別名、80:20の法則、もう1つの別名、ばらつきの法則）と呼ぶ。

ここでは、仮想の企業の需要を生成し、それに対してABC分析を行う。
同時に、商品を売れている順に順位をつけ、順位の時系列的な変化を示すランク分析を提案する。

さらに、簡単な在庫分析を行う。これは、平均需要量や生産固定費用から、生産ロットサイズや安全在庫量を計算するものであり、
古典的な経済発注量モデルや安全在庫モデル（新聞売り子モデル）に基づくものである。

## データの読み込み

まずは基本となるデータを読み込む。製品データはオプションであり、需要を売り上げや需要を重量や容量で評価したい場合に使う。
基本は、需要データ demand_df だけを使えば十分である。

需要データは以下の列をもつ．

- date: 日付
- cust: 顧客名
- prod: 製品名
- demand: 需要量
- sales: 売上

需要量demandと売上の何れかに対して，ABC分析を行う．

``` python
prod_df = pd.read_csv(folder+"Prod.csv",index_col=0)
prod_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">name</th>
<th data-quarto-table-cell-role="th">weight</th>
<th data-quarto-table-cell-role="th">volume</th>
<th data-quarto-table-cell-role="th">cust_value</th>
<th data-quarto-table-cell-role="th">dc_value</th>
<th data-quarto-table-cell-role="th">plnt_value</th>
<th data-quarto-table-cell-role="th">fixed_cost</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>A</td>
<td>2</td>
<td>0</td>
<td>7</td>
<td>1</td>
<td>1</td>
<td>14</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>B</td>
<td>5</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>14</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>C</td>
<td>1</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>19</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>D</td>
<td>3</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>17</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>E</td>
<td>1</td>
<td>0</td>
<td>10</td>
<td>1</td>
<td>1</td>
<td>18</td>
</tr>
</tbody>
</table>

</div>

``` python
demand_df = pd.read_csv(folder+"demand.csv",index_col=0)
demand_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">sales</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">index</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>A</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>B</td>
<td>10</td>
<td>10</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>C</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>D</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2019-01-01</td>
<td>札幌市</td>
<td>E</td>
<td>37</td>
<td>37</td>
</tr>
</tbody>
</table>

</div>

### Kaggleデータの読み込み

以下で配布されているデータを読み込む．

https://www.kaggle.com/kyanyoga/sample-sales-data

Kaggleデータを用いたい場合には，以下を実行する．
ただし，製品データがないので，製品関連の関数は適用できない．

``` python
kaggle_df = pd.read_csv(folder + "sales_data_sample.csv",encoding="latin")
kaggle_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">ORDERNUMBER</th>
<th data-quarto-table-cell-role="th">QUANTITYORDERED</th>
<th data-quarto-table-cell-role="th">PRICEEACH</th>
<th data-quarto-table-cell-role="th">ORDERLINENUMBER</th>
<th data-quarto-table-cell-role="th">SALES</th>
<th data-quarto-table-cell-role="th">ORDERDATE</th>
<th data-quarto-table-cell-role="th">STATUS</th>
<th data-quarto-table-cell-role="th">QTR_ID</th>
<th data-quarto-table-cell-role="th">MONTH_ID</th>
<th data-quarto-table-cell-role="th">YEAR_ID</th>
<th data-quarto-table-cell-role="th">...</th>
<th data-quarto-table-cell-role="th">ADDRESSLINE1</th>
<th data-quarto-table-cell-role="th">ADDRESSLINE2</th>
<th data-quarto-table-cell-role="th">CITY</th>
<th data-quarto-table-cell-role="th">STATE</th>
<th data-quarto-table-cell-role="th">POSTALCODE</th>
<th data-quarto-table-cell-role="th">COUNTRY</th>
<th data-quarto-table-cell-role="th">TERRITORY</th>
<th data-quarto-table-cell-role="th">CONTACTLASTNAME</th>
<th data-quarto-table-cell-role="th">CONTACTFIRSTNAME</th>
<th data-quarto-table-cell-role="th">DEALSIZE</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>10107</td>
<td>30</td>
<td>95.70</td>
<td>2</td>
<td>2871.00</td>
<td>2/24/2003 0:00</td>
<td>Shipped</td>
<td>1</td>
<td>2</td>
<td>2003</td>
<td>...</td>
<td>897 Long Airport Avenue</td>
<td>NaN</td>
<td>NYC</td>
<td>NY</td>
<td>10022</td>
<td>USA</td>
<td>NaN</td>
<td>Yu</td>
<td>Kwai</td>
<td>Small</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>10121</td>
<td>34</td>
<td>81.35</td>
<td>5</td>
<td>2765.90</td>
<td>5/7/2003 0:00</td>
<td>Shipped</td>
<td>2</td>
<td>5</td>
<td>2003</td>
<td>...</td>
<td>59 rue de l'Abbaye</td>
<td>NaN</td>
<td>Reims</td>
<td>NaN</td>
<td>51100</td>
<td>France</td>
<td>EMEA</td>
<td>Henriot</td>
<td>Paul</td>
<td>Small</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>10134</td>
<td>41</td>
<td>94.74</td>
<td>2</td>
<td>3884.34</td>
<td>7/1/2003 0:00</td>
<td>Shipped</td>
<td>3</td>
<td>7</td>
<td>2003</td>
<td>...</td>
<td>27 rue du Colonel Pierre Avia</td>
<td>NaN</td>
<td>Paris</td>
<td>NaN</td>
<td>75508</td>
<td>France</td>
<td>EMEA</td>
<td>Da Cunha</td>
<td>Daniel</td>
<td>Medium</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>10145</td>
<td>45</td>
<td>83.26</td>
<td>6</td>
<td>3746.70</td>
<td>8/25/2003 0:00</td>
<td>Shipped</td>
<td>3</td>
<td>8</td>
<td>2003</td>
<td>...</td>
<td>78934 Hillside Dr.</td>
<td>NaN</td>
<td>Pasadena</td>
<td>CA</td>
<td>90003</td>
<td>USA</td>
<td>NaN</td>
<td>Young</td>
<td>Julie</td>
<td>Medium</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>10159</td>
<td>49</td>
<td>100.00</td>
<td>14</td>
<td>5205.27</td>
<td>10/10/2003 0:00</td>
<td>Shipped</td>
<td>4</td>
<td>10</td>
<td>2003</td>
<td>...</td>
<td>7734 Strong St.</td>
<td>NaN</td>
<td>San Francisco</td>
<td>CA</td>
<td>NaN</td>
<td>USA</td>
<td>NaN</td>
<td>Brown</td>
<td>Julie</td>
<td>Medium</td>
</tr>
</tbody>
</table>

<p>5 rows × 25 columns</p>
</div>

``` python
kaggle_df["date"] = pd.to_datetime(kaggle_df.ORDERDATE)
kaggle_df.rename(columns={"PRODUCTLINE":"prod", "CITY":"cust", "QUANTITYORDERED":"demand", "SALES":"sales"}, inplace=True)
demand_df = kaggle_df[["date","cust","prod","demand","sales"]].copy()
demand_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">sales</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>2003-02-24</td>
<td>NYC</td>
<td>Motorcycles</td>
<td>30</td>
<td>2871.00</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>2003-05-07</td>
<td>Reims</td>
<td>Motorcycles</td>
<td>34</td>
<td>2765.90</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>2003-07-01</td>
<td>Paris</td>
<td>Motorcycles</td>
<td>41</td>
<td>3884.34</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>2003-08-25</td>
<td>Pasadena</td>
<td>Motorcycles</td>
<td>45</td>
<td>3746.70</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>2003-10-10</td>
<td>San Francisco</td>
<td>Motorcycles</td>
<td>49</td>
<td>5205.27</td>
</tr>
</tbody>
</table>

</div>

## 需要と売り上げのtreemapを生成する関数 demand_tree_map

引数： - 需要データフレーム（需要 demand と売り上げ sales の列を含む）

返値： - Plotlyのtreemapオブジェクト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L33"
target="_blank" style="float:right; font-size:smaller">source</a>

### demand_tree_map

``` python

def demand_tree_map(
    demand_df
):

```

*需要と売り上げのtreemapを生成する関数*

### demand_tree_mapの使用例

sales列がない場合には，dataモジュールのdemand_attribute_compute関数を用いてsales（売り上げ）列を計算することができる。

需要のtreemapは，需要の大きさを面積とした階層図であり，売上は色で表現している．

``` python
fig = demand_tree_map(demand_df);
plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-12-output-1.png)

## ABC分析とランク分析を行うための関数 abc_analysis

ABC分析のための関数を記述する、基本的には、需要データ demand_df
だけあれば良いが、顧客や製品に関連した量を分析に加えたいときには、顧客データ
cust_df や 製品データ prod_df も読み込んでおく。

古典的なABC分析では、3つのカテゴリーに製品や顧客を分類していたが、場合によっては4つに分類したい場合もあるだろう。
ここでは、より一般的にユーザーが与えた任意の数への分類を行う関数を準備する、カテゴリーに含まれる需要量を、ユーザーが与えた閾値をもとにして分類を行う。

引数:

- df:
  ABC分析を行うための需要データフレーム．列に集約を行うための列と値を格納した列が必要．
- threshold: A,B,C の分類を行うための閾値．上位
  threshold\[0\]の要素がAランク，次に上位の
  threshold\[1\]がBランク、と順に決めていく。
  リストの長さは（アルファベットの数以下の）任意の正数であるが、合計が1以上になるような数値のリストとして与える．
- agg_col: 集約を行う列名を文字列として与える．
- value_column:
  A,B,Cの分類を行うための数値データを保管した列名を文字列として与える．
- abc_name: 分類した結果を入れるための列名を文字列として与える．
- rank_name: 数値データの順位を入れた列名を文字列として与える．

返値: 以下の3つのオブジェクトのタプル：

- agg_df:
  agg_colによって集約したデータをvalue_columnの数値の大きい順に並べたデータフレーム．abcとrankの情報が付加されている．
- new_df:
  元のデータフレームにabc_nameで与えた列にA(=0),B(=1),C(=2)の分類を，rank_nameで与えた列にランク（順位）を入れている．
- category: 0,1,2, …をキーとして与えると A,B,C,…
  ランクに属するデータ名（agg_colの要素）のリストを値として返す辞書．

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L51"
target="_blank" style="float:right; font-size:smaller">source</a>

### abc_analysis

``` python

def abc_analysis(
    df, threshold, agg_col, value_column, abc_name, rank_name
):

```

*ABC分析のための関数*

### 顧客・製品の組に対するABC分析 abc_analysis_all

顧客・製品ごとに需要予測を行う際に，予測しなくても良い組を予め抜き出しておくことが重要になる．そのため，顧客・製品の組に対してABC分析とランク分析を行う関数を準備しておく．

引数:

- 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の要素）のリストを値として返す辞書．

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L114"
target="_blank" style="float:right; font-size:smaller">source</a>

### abc_analysis_all

``` python

def abc_analysis_all(
    df, threshold
):

```

*Call self as a function.*

## 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\]を用いて分類

\#hide - 製品を売り上げを元に4つのクラスに、閾値\[0.6, 0.2, 0.1,
0.1\]を用いて分類
（これを行うためには、data_generationモジュールのdemand_attribute_compute関数で、Salesの列を生成しておく必要がある。）

``` python
agg_df_prod, new_df, category_prod = abc_analysis(
    demand_df, [0.4, 0.5, 0.1], 'prod', 'demand', "prod_ABC", "prod_rank")
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()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">index</th>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">sales</th>
<th data-quarto-table-cell-role="th">abc</th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">prod_ABC</th>
<th data-quarto-table-cell-role="th">prod_rank</th>
<th data-quarto-table-cell-role="th">customer_ABC</th>
<th data-quarto-table-cell-role="th">customer_rank</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">date</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">2003-02-24</td>
<td>0</td>
<td>NYC</td>
<td>Motorcycles</td>
<td>30</td>
<td>2871.00</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>2</td>
<td>A</td>
<td>2</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2003-05-07</td>
<td>1</td>
<td>Reims</td>
<td>Motorcycles</td>
<td>34</td>
<td>2765.90</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>17</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2003-07-01</td>
<td>2</td>
<td>Paris</td>
<td>Motorcycles</td>
<td>41</td>
<td>3884.34</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>2</td>
<td>A</td>
<td>4</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2003-08-25</td>
<td>3</td>
<td>Pasadena</td>
<td>Motorcycles</td>
<td>45</td>
<td>3746.70</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>32</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2003-10-10</td>
<td>4</td>
<td>San Francisco</td>
<td>Motorcycles</td>
<td>49</td>
<td>5205.27</td>
<td>B</td>
<td>2</td>
<td>B</td>
<td>2</td>
<td>A</td>
<td>5</td>
</tr>
</tbody>
</table>

</div>

``` python
agg_df_prod.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">abc</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">Classic Cars</td>
<td>33992</td>
<td>0</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Vintage Cars</td>
<td>21069</td>
<td>1</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Motorcycles</td>
<td>11663</td>
<td>2</td>
<td>B</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Trucks and Buses</td>
<td>10777</td>
<td>3</td>
<td>B</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Planes</td>
<td>10727</td>
<td>4</td>
<td>B</td>
</tr>
</tbody>
</table>

</div>

``` python
agg_df_cust.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">abc</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">Madrid</td>
<td>10958</td>
<td>0</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">San Rafael</td>
<td>6366</td>
<td>1</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">NYC</td>
<td>5294</td>
<td>2</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Singapore</td>
<td>2760</td>
<td>3</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Paris</td>
<td>2521</td>
<td>4</td>
<td>A</td>
</tr>
</tbody>
</table>

</div>

``` python
agg_df,category = abc_analysis_all(demand_df, threshold=[0.4, 0.3, 0.3, 0.1])
agg_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">sum</th>
<th data-quarto-table-cell-role="th">std</th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">abc</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">cust</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">Madrid</td>
<td data-quarto-table-cell-role="th">Classic Cars</td>
<td>4139</td>
<td>9.376234</td>
<td>0</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">San Rafael</td>
<td data-quarto-table-cell-role="th">Classic Cars</td>
<td>2381</td>
<td>9.336030</td>
<td>1</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">NYC</td>
<td data-quarto-table-cell-role="th">Classic Cars</td>
<td>2306</td>
<td>9.134373</td>
<td>2</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">Madrid</td>
<td data-quarto-table-cell-role="th">Vintage Cars</td>
<td>2272</td>
<td>8.772440</td>
<td>3</td>
<td>A</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">San Rafael</td>
<td data-quarto-table-cell-role="th">Vintage Cars</td>
<td>1753</td>
<td>8.389640</td>
<td>4</td>
<td>A</td>
</tr>
</tbody>
</table>

</div>

### 元のデータフレームにabcとrankとdemandを追加する関数 add_abc

引数： - df:
製品や顧客のデータフレーム；これにABC分析の結果を追加する． - agg_df:
集約した需要，ABC分類，ランクを保管したデータフレーム；インデックスは製品(prod)もしくは顧客
(cust) - col_name:
追加したいデータの列名；製品の場合にはprod（既定値），顧客の場合にはcust

返値： - df: ランク，ABC分類，集約した需要量を追加したデータフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L159"
target="_blank" style="float:right; font-size:smaller">source</a>

### add_abc

``` python

def add_abc(
    df, agg_df, col_name:str='prod'
):

```

*Call self as a function.*

### add_abc関数の使用例

``` python
new_prod_df = add_abc(prod_df, agg_df_prod)
new_prod_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">name</th>
<th data-quarto-table-cell-role="th">plnt_value</th>
<th data-quarto-table-cell-role="th">fixed_cost</th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">abc</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>A</td>
<td>1</td>
<td>14</td>
<td>18026</td>
<td>3</td>
<td>B</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>B</td>
<td>1</td>
<td>14</td>
<td>17592</td>
<td>4</td>
<td>B</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>C</td>
<td>1</td>
<td>19</td>
<td>6682</td>
<td>7</td>
<td>C</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>D</td>
<td>1</td>
<td>17</td>
<td>813</td>
<td>9</td>
<td>C</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>E</td>
<td>1</td>
<td>18</td>
<td>77704</td>
<td>0</td>
<td>A</td>
</tr>
</tbody>
</table>

</div>

## ABC別に色分けした需要のtreemapを生成する関数

引数： - 需要データフレーム（需要 demand，売り上げ sales，customer_ABC,
prod_ABCの列を含む； ABC分析で得られたnew_df）

返値： - Plotlyのtreemapオブジェクト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L178"
target="_blank" style="float:right; font-size:smaller">source</a>

### demand_tree_map_with_abc

``` python

def demand_tree_map_with_abc(
    demand_df
):

```

*ABC別に色分けした需要のtreemapを生成する関数*

### demand_tree_map_with_abc関数の使用例

``` python
fig = demand_tree_map_with_abc(new_df)
plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-25-output-1.png)

### 需要データフレームからABC分析の図とデータフレームを生成する関数 generate_figures_for_abc_analysis

顧客と製品の両方に対するABC分析を同時に行い、結果の図とデータフレームを同時に得るには、この関数を用いる。

引数：

- demand_df : 需要データフレーム
- value_name: 分析をするデータが入っている列名（既定値は”demand”）
- cumsum : 図を累積値で描画するときには True
- cust_thres : 顧客のABC分析するときの閾値を文字列で表したもの
- prod_thres : 製品のABC分析するときの閾値を文字列で表したもの

返値：

- fig_prod : 製品のABC分析のPlotly図オブジェクト
- fig_cust : 顧客のABC分析のPlotly図オブジェクト
- agg_df_prod : 製品をインデックスとしたABC分析のデータフレーム
- agg_df_cust : 顧客をインデックスとしたABC分析のデータフレーム
- new_df : 顧客と製品のABCとランクを加えた新しい需要データフレーム

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L198"
target="_blank" style="float:right; font-size:smaller">source</a>

### generate_figures_for_abc_analysis

``` python

def generate_figures_for_abc_analysis(
    demand_df, value_name:str='demand', cumsum:bool=True, cust_thres:str='0.7, 0.2, 0.1',
    prod_thres:str='0.7, 0.2, 0.1'
):

```

*Call self as a function.*

### generate_figures_for_abc_analysis関数の使用例

``` python
fig_prod, fig_cust, agg_df_prod, agg_df_cust, new_df = generate_figures_for_abc_analysis(
demand_df, value_name="sales", cumsum = False, cust_thres="0.7, 0.2, 0.1", prod_thres="0.7, 0.2, 0.1")
plotly.offline.plot(fig_prod);
```

![](01abc_files/figure-commonmark/cell-28-output-1.png)

![](01abc_files/figure-commonmark/cell-29-output-1.png)

## ランク分析のための関数 rank_analysis と rank_analysis_all_periods

全ての期に対するランク分析を行う関数 rank_analysis
と、期ごと（集約する単位は文字列で与える）のランク分析を行う関数
rank_analysis_all_periodsを記述する。

引数:

- df:
  ランク分析を行う対象の需要データフレーム．列に集約を行うための列と，値を格納した列が必要．
- agg_col: 集約を行う列名を文字列として与える．
- value_column:
  ランクを計算するための数値データを保管した列名を文字列として与える．
- agg_period （rank_analysis_all_periodsの場合のみ） : 集約を行う期間を
  “1m”（月次）のような文字列で与える．

返値:

- 名前を入れるとランク（rank_analysisの場合）もしくランクの期別リスト（rank_analysis_all_periodsの場合）を返す辞書

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L279"
target="_blank" style="float:right; font-size:smaller">source</a>

### rank_analysis

``` python

def rank_analysis(
    df, agg_col, value_column
):

```

*全期間分のランク分析のための関数*

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L293"
target="_blank" style="float:right; font-size:smaller">source</a>

### rank_analysis_all_periods

``` python

def rank_analysis_all_periods(
    df, agg_col, value_col, agg_period
):

```

*期別のランク分析のための関数*

### ランク分析の関数の使用例

全期間分の顧客需要のランク分析と、３ヶ月を１期とした各期間に対する製品のランク分析。

``` python
dic = rank_analysis(demand_df, 'cust', 'demand') #全ての期間に対する顧客需要量のランク分析
dic.popitem()
```

    ('Charleroi', 73)

``` python
dic = rank_analysis_all_periods(demand_df, 'prod', 'demand', "1d") 
#dic.popitem()
```

### ランク分析の可視化関数 show_rank_analysis

ランクの時系列的な変化を表す図を生成するための関数。

引数:

- df:
  ランク分析を行う対象の需要データフレーム．列に集約を行うための列と，値を格納した列が必要．
- value_name: 分析をするデータが入っている列名（既定値は”demand”）
- agg_period: 集約を行う期間を “1m”（月次）のような文字列で与える．
- top_rank: 上位 top_rank 個のものだけを表示する

返値:

- Plotlyの図オブジェクト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L322"
target="_blank" style="float:right; font-size:smaller">source</a>

### show_rank_analysis

``` python

def show_rank_analysis(
    demand_df, value_name:str='demand', agg_period:str='1m', top_rank:int=1
):

```

*ランク分析の可視化関数*

### show_rank_analysis関数の使用例

``` python
fig = show_rank_analysis(demand_df, value_name="sales", agg_period ="1d", top_rank = 10)
plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-38-output-1.png)

## リスク共同管理分析 risk_pooling_analysis

在庫をサプライ・チェインの上流（供給側）でもつか、下流（需要側）でもつかは、複数の需要地点（顧客）における需要の相関で決まる。
一般には、上流で在庫を共有することによって在庫の削減ができる。これをリスク共同管理
(risk pooling) とよぶ。

ここでは、製品ごとに、顧客の需要の標準偏差とリスク共同管理した場合の標準偏差の差を計算する。
また、それを需要の総量で割った比率（削減率）も計算する。
これは、標準偏差を平均値で割ることによる無次元の指標（変動係数：
coefficient of variation: CV)に相当するものである。

この値が大きい製品ほど、リスク共同管理の効果が大きいので、サプライ・チェインの上流で在庫を保持した方が良いことになり、
逆に小さい製品ほど、下流で在庫を保持した方が良いことになる。

引数： - demand_df: 需要のデータフレーム - agg_period:
標準偏差を計算する際に用いる需要の集約を行う期（規定値は週）

返値： - inv_reduction_df :
標準偏差とその差と削減率を製品ごとに計算したデータフレーム；
Rank列は製品の順位

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L369"
target="_blank" style="float:right; font-size:smaller">source</a>

### risk_pooling_analysis

``` python

def risk_pooling_analysis(
    demand_df, agg_period:str='1w'
):

```

*リスク共同管理の効果を見るための関数*

在庫を顧客側においた場合と、倉庫側においた場合の差を、標準偏差を計算することによって推定する。

## risk_pooling_analysis関数の使用例

１週間を単位とした標準偏差をもとに、在庫を倉庫に置いた場合と工場に置いた場合の差を計算し、それを需要の総量で除した削減率(ReductionRatioの列）を計算する。
Plotlyによる可視化では、削減率の大きいものから棒グラフで表示し、需要の大きさのランクで色分けをする。

``` python
inv_reduction_df = risk_pooling_analysis(demand_df, agg_period="1w")
inv_reduction_df.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">rank</th>
<th data-quarto-table-cell-role="th">prod</th>
<th data-quarto-table-cell-role="th">agg_std</th>
<th data-quarto-table-cell-role="th">sum_std</th>
<th data-quarto-table-cell-role="th">reduction</th>
<th data-quarto-table-cell-role="th">reduction_ratio</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>10</td>
<td>D</td>
<td>20.506097</td>
<td>61.518290</td>
<td>41.012193</td>
<td>0.050446</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>9</td>
<td>I</td>
<td>101.823376</td>
<td>142.835570</td>
<td>41.012193</td>
<td>0.016353</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>8</td>
<td>C</td>
<td>302.641702</td>
<td>332.340187</td>
<td>29.698485</td>
<td>0.004445</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>4</td>
<td>A</td>
<td>749.533188</td>
<td>782.060100</td>
<td>32.526912</td>
<td>0.001804</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>7</td>
<td>F</td>
<td>513.359523</td>
<td>524.673232</td>
<td>11.313708</td>
<td>0.000956</td>
</tr>
</tbody>
</table>

</div>

### 在庫削減量の可視化関数 show_inventory_reduction

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L419"
target="_blank" style="float:right; font-size:smaller">source</a>

### show_inventory_reduction

``` python

def show_inventory_reduction(
    inv_reduction_df
):

```

*在庫削減量の可視化関数*

``` python
fig = show_inventory_reduction(inv_reduction_df)
plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-43-output-1.png)

### 需要の製品ごとの平均と変動係数の可視化関数 show_mean_cv

需要を製品ごとに集約し，横軸に平均，縦軸に変動係数(*C**V* = *σ*/*μ*)の対数をとった散布図を生成する．

平均が大きく，変動係数が小さい製品は安定しているので倉庫（サプライ・チェインの下流）で保管し，平均が小さく変動係数が大きい製品は，工場（サプライ・チェインの上流）で
保管し，適宜顧客側に流す戦略が望ましい．

引数： - demand: 需要データフレーム - show_name:
Trueのとき製品名も描画する．

返値： - fig: Plotlyの図オブジェクト

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L432"
target="_blank" style="float:right; font-size:smaller">source</a>

### show_mean_cv

``` python

def show_mean_cv(
    demand_df, show_name:bool=True
):

```

*Call self as a function.*

#### show_mean_cv関数の使用例

``` python
fig = show_mean_cv(demand_df, show_name=True)
#plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-46-output-1.png)

## 安全在庫、ロットサイズ、目標在庫（基在庫レベル）の設定関数 inventory_analysis

全ての需要が1つの工場で生産していると仮定したとき、その生産ロットサイズや安全在庫量は、古典的な経済発注量モデルと新聞売り子モデルで計算できる。

- 安全在庫量: 安全在庫係数 *z*, リード時間 *L*， 需要の標準偏差 *σ*
  としたとき $z\sqrt{LT}\sigma$

- 経済発注量（生産ロットサイズ）: 生産固定費用 *F**C*、需要の平均値
  *d*、在庫費用 *h* としたとき $\sqrt{2 FCd/h}$

- 保管費率（無次元）： *r* は以下の量の和とする。

  1.  利子率（投資額利率）
  2.  保険料率: 製品の種類および企業の方針によっても異なる．
  3.  消耗費率および陳腐化率: 製品の腐敗，破損，目減りなどを考慮して計算
  4.  税率: 在庫に課せられる法的な税率（日本では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週間に換算したもの
- safety_inventory: 安全在庫量
- target_inventory: 目標在庫量（基在庫レベル）；　
  $d LT + z\sqrt{LT}\sigma$
- initial_inventory: 初期在庫量

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L451"
target="_blank" style="float:right; font-size:smaller">source</a>

### inventory_analysis

``` python

def inventory_analysis(
    prod_df, demand_df, inv_reduction_df, z:float=1.65, LT:int=1, r:float=0.3, num_days:int=7
):

```

*工場における安全在庫量の計算*

工場を１箇所に集約したと仮定する。複数工場の場合には、顧客と工場の紐付け情報が必要になる。

### inventory_analysis関数の使用例

１週間を基本単位として、在庫量削減データフレームを計算し、それをもとに工場での在庫量を求める。

``` python
prod_df = pd.read_csv(folder+"Prod.csv",index_col=0)

inv_reduction_df = risk_pooling_analysis(demand_df, agg_period="1w")
prod_df2 = inventory_analysis(prod_df, demand_df, inv_reduction_df, z = 1.65, LT = 1, r = 0.3, num_days=7)
prod_df2.set_index("index", inplace=True)
prod_df2.to_csv(folder + "Prod_with_inventory.csv")
prod_df2.head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">name</th>
<th data-quarto-table-cell-role="th">weight</th>
<th data-quarto-table-cell-role="th">volume</th>
<th data-quarto-table-cell-role="th">cust_value</th>
<th data-quarto-table-cell-role="th">dc_value</th>
<th data-quarto-table-cell-role="th">plnt_value</th>
<th data-quarto-table-cell-role="th">fixed_cost</th>
<th data-quarto-table-cell-role="th">average_demand</th>
<th data-quarto-table-cell-role="th">standard_deviation</th>
<th data-quarto-table-cell-role="th">inv_cost</th>
<th data-quarto-table-cell-role="th">lot_size</th>
<th data-quarto-table-cell-role="th">safety_inventory</th>
<th data-quarto-table-cell-role="th">target_inventory</th>
<th data-quarto-table-cell-role="th">initial_inventory</th>
</tr>
<tr>
<th data-quarto-table-cell-role="th">index</th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th"></th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">0</td>
<td>A</td>
<td>2</td>
<td>0</td>
<td>7</td>
<td>1</td>
<td>1</td>
<td>14</td>
<td>11471.090909</td>
<td>749.533188</td>
<td>0.005753</td>
<td>7471.678242</td>
<td>1236.729760</td>
<td>8708.408003</td>
<td>4972.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">1</td>
<td>B</td>
<td>5</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>14</td>
<td>11194.909091</td>
<td>760.846897</td>
<td>0.005753</td>
<td>7381.184926</td>
<td>1255.397379</td>
<td>8636.582305</td>
<td>4945.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2</td>
<td>C</td>
<td>1</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>19</td>
<td>4252.181818</td>
<td>302.641702</td>
<td>0.005753</td>
<td>5299.495116</td>
<td>499.358809</td>
<td>5798.853925</td>
<td>3149.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">3</td>
<td>D</td>
<td>3</td>
<td>0</td>
<td>5</td>
<td>1</td>
<td>1</td>
<td>17</td>
<td>517.363636</td>
<td>20.506097</td>
<td>0.005753</td>
<td>1748.534451</td>
<td>33.835059</td>
<td>1782.369511</td>
<td>908.0</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">4</td>
<td>E</td>
<td>1</td>
<td>0</td>
<td>10</td>
<td>1</td>
<td>1</td>
<td>18</td>
<td>49448.000000</td>
<td>3426.639462</td>
<td>0.005753</td>
<td>17589.860716</td>
<td>5653.955112</td>
<td>23243.815827</td>
<td>14448.0</td>
</tr>
</tbody>
</table>

</div>

## 生産・在庫シミュレーション inventory_simulation

上で生成したデータを用いて、シミュレーションを行う。生産は、安全在庫量を下回ったときに行われ、目標在庫量になるように生産量を決める。

引数：

- prod_df: 製品データ
- demand_df: 需要データ

返値：

- キーを製品名、値を、需要 demand、在庫 inventory、生産量 production
  を列とした時系列データフレームとした辞書

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L492"
target="_blank" style="float:right; font-size:smaller">source</a>

### inventory_simulation

``` python

def inventory_simulation(
    prod_df, demand_df
):

```

*(Q,R)方策のシミュレーション*

### inventory_simulation関数の使用例

製品 A に対する需要、在庫、生産量を表すデータフレームを表示する。

``` python
production_df = inventory_simulation(prod_df, demand_df)
production_df[prod_df.name[0]].head()
```

<div>
<style scoped>
    .dataframe tbody tr th:only-of-type {
        vertical-align: middle;
    }
&#10;    .dataframe tbody tr th {
        vertical-align: top;
    }
&#10;    .dataframe thead th {
        text-align: right;
    }
</style>

<table class="dataframe" data-quarto-postprocess="true" data-border="1">
<thead>
<tr style="text-align: right;">
<th data-quarto-table-cell-role="th"></th>
<th data-quarto-table-cell-role="th">demand</th>
<th data-quarto-table-cell-role="th">inventory</th>
<th data-quarto-table-cell-role="th">production</th>
</tr>
</thead>
<tbody>
<tr>
<td data-quarto-table-cell-role="th">2019-01-01</td>
<td>1397</td>
<td>3575.000000</td>
<td>0.000000</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-02</td>
<td>1684</td>
<td>1891.000000</td>
<td>0.000000</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-03</td>
<td>1796</td>
<td>95.000000</td>
<td>8613.408003</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-04</td>
<td>1249</td>
<td>7459.408003</td>
<td>0.000000</td>
</tr>
<tr>
<td data-quarto-table-cell-role="th">2019-01-05</td>
<td>2083</td>
<td>5376.408003</td>
<td>0.000000</td>
</tr>
</tbody>
</table>

</div>

### 生産、在庫、需要の可視化関数 show_prod_inv_demand

------------------------------------------------------------------------

<a
href="https://github.com/scmopt/manual/tree/master/blob/master/scmopt/abc.py#L518"
target="_blank" style="float:right; font-size:smaller">source</a>

### show_prod_inv_demand

``` python

def show_prod_inv_demand(
    prod_name, production_df, scale:str='1d'
):

```

*生産、在庫、需要の可視化関数*

### show_prod_inv_demand関数の使用例

``` python
fig = show_prod_inv_demand(prod_df.name[3], production_df, scale="1d")
plotly.offline.plot(fig);
```

![](01abc_files/figure-commonmark/cell-53-output-1.png)

\#hide \## 生産、需要、在庫の可視化

上で作成した production_df
をDashで可視化するインターフェイスを作成する。

\#hide \## Dashを用いたABC分析のダッシュボード

demand_dfを用いて、ABC分析、ランク分析、リスク共同管理分析を行う。
