藥庫是醫院的藥品的倉庫,管理模式其實也可以比照一般商業或行銷的模式,把藥品當成貨品管理,差別在於本院採行的「帳料分離」的形式,也就是貨品管理倉庫的這一端無法得知所有藥品的購買成本,因此在對應一般商管手法時,我們會直接把售價當作成本價來進行計算,在沒有特別考量的情形下,成本和售價之間是有一定的公式換算關係。

當我們有了藥品的售價和藥品在倉庫裡的存量之後,就可以知道目前藥庫的靜態庫存持有成本,最佳的庫存持有成本當然是越低越好,最好的情形當然是無庫存,藥品由廠商出貨後直接被使用掉,簡直完美但是不可能達成,畢竟缺藥的風險太大了,藥品跟其他貨品更無法容忍暫時缺貨的情形,因此倉庫裡面還是得保有一定的安全庫存,但如果每一個品項的安全庫存都一樣,庫存成本又會太高,因此我們採用了 ABC 分析法來對本院的藥品分類,依照類別來調整各自的安全庫存。


什麼是 ABC 分析法?

ABC 分析法有超級多的名字:帕累托 (Pareto) 分析法、主次因分析法、柏拉圖分析、分類管理法、重點管理法等等。是基於 Pareto principle 帕累托法則將庫存的貨品依照年度銷售總額進行分級分類的技術,將貨品分成三個等級:

  • 等級 A :年度銷售總額最高,但品項數相對是少數的一群。
  • 等級 B :年度銷售總額居中,品項數居中。
  • 等級 C :年度銷售總額低,品項數相對佔比較多的一群。

A 類的物品被視為高價值的物品,只要少少一點就可以創造極高的利潤,或是少少一點就可能劇烈的影響庫存成本,B 類物品次之,而 C 類物品則是最低價值的物品,大量的存在也不會影響總體的利潤或是庫存成本,比較可以不用花費心思或是管理成本在上面。

ABC analysis

因此我們只需要將集中處理 A 類物品,嚴格控制 A 類的庫存, B 類次之, C 類隨便就採用相對普通的管理,如此一來除了節省大部分的心力與人力,還能壓低庫存成本。

我們一邊看下面的例子一邊把剩下的部分講完。


ABC 分析法的計算

要進行 ABC 分析法,必須要有物品的兩個資訊:年度銷售數量物品成本

讓我們假設一下有一家文具店的銷售情形如下:

物品名稱,年度銷售數量,物品成本
鉛筆,360,10
自動筆,480,20
原子筆,1300,30
彩色筆,320,20
奇異筆,260,30
粉筆,10,5
白板筆,180,40
雷射筆,10,300
觸控筆,90,200
水彩筆,230,30
毛筆,30,30
蠟筆,700,20
螢光筆,800,20

年度銷售數量 × 物品成本得到年度銷售金額

物品名稱,年度銷售金額
鉛筆,3600
自動筆,9600
原子筆,39000
彩色筆,6400
奇異筆,7800
粉筆,50
白板筆,7200
雷射筆,3000
觸控筆,18000
水彩筆,6900
毛筆,900
蠟筆,14000
螢光筆,16000

也可以得到這家文具店所有筆種年度銷售金額總和: 132,450 元。

按照年度銷售金額將貨品降冪 (大到小) 排序:

物品名稱,年度銷售金額
原子筆,39000
觸控筆,18000
螢光筆,16000
蠟筆,14000
自動筆,9600
奇異筆,7800
白板筆,7200
水彩筆,6900
彩色筆,6400
鉛筆,3600
雷射筆,3000
毛筆,900
粉筆,50

大概就可以知道越前面的物品價值越高,越後面的物品價值越低,也就是對這家文具店而言,原子筆、觸控筆和螢光筆的銷售相比於毛筆或粉筆的銷售還來的重要,因此甚至可以跟向該文具店建議,店內的貨架主要放置原子筆、觸控筆和螢光筆,可以達到最大的好處。

那 ABC 之間的界線在哪裡?該怎麼設定?我們繼續看下去:

接著計算每個貨品年度銷售金額的累加值

物品名稱,年度銷售金額,累加值
原子筆,39000,39000
觸控筆,18000,57000
螢光筆,16000,73000
蠟筆,14000,87000
自動筆,9600,96600
奇異筆,7800,104400
白板筆,7200,111600
水彩筆,6900,118500
彩色筆,6400,124900
鉛筆,3600,128500
雷射筆,3000,121500
毛筆,900,132400
粉筆,50,132450

如果把貨品的累加值拿去作圖,可以得到 ABC 分析法的經典曲線。

ABC analysis

 

計算累加值 ÷ 年度銷售總額並取成百分比:

物品名稱,年度銷售總額,累加百分比
原子筆,39000,29%
觸控筆,18000,43%
螢光筆,16000,55%
蠟筆,14000,66%
自動筆,9600,73%
奇異筆,7800,79%
白板筆,7200,84%
水彩筆,6900,89%
彩色筆,6400,94%
鉛筆,3600,97%
雷射筆,3000,99%
毛筆,900,100%
粉筆,50,100%

百分比取出來之後,就可以訂定適合的 ABC 類物品的界限,這個界限的設定值沒有標準,要依照各家公司行號的銷售標準來設定,不過大部分其實都差不多,按照維基百科的設定: A 類 70% 、 B類 25% 、 C 類 5% ,以文具店來分就是:

  • A 類 (0%-70%) :原子筆、觸控筆、螢光筆、蠟筆
  • B 類 (71%-95%) :自動筆、奇異筆、白板筆、水彩筆、彩色筆
  • C 類 (96%-100%) :鉛筆、雷射筆、毛筆、粉筆

Oracle 公司推出的 ERP 軟體中設定 A 類 70-80% 、 B類 15-20% 、 C 類 5% 。

如此就可以為各自的分類訂出銷售策略或是庫存數量基準。

ABC 分析法前後的庫存成本差異

用上面的例子來看看 ABC 分析法介入的前後:

ABC 分析法介入前,文具店將每種筆的庫存都訂為 50 支,因此庫存金額為 37750 元;

ABC 分析法介入後,我們建議 A 類的貨品應該精準控制庫存, B 類次之;因此將 A 類的貨品庫存訂為 10 支, B 類維持 50 支, C 類放寬為 70 支,如此庫存金額為 33850 元,降低了不少。

品項數如果少的話看起來的確是廢話,但是如果品項數很多,成效就會十分顯著。


Python 實作 ABC 分析法

接著,我們看看以 Python 實作醫院藥品 ABC 分析法: 

引入函式庫、設定資料庫連線,這個資料庫是使用藥品消耗資料視覺化一文中已經建立的資料庫。

import pandas as pd
import numpy as np
import mysql.connector
from sqlalchemy import create_engine
engine = create_engine('mysql+mysqlconnector://使用者名稱:密碼@伺服器存在位置IP:埠號/資料庫名稱')

 

  1. 計算每個藥品一年度的消耗量總和
start_date = (pd.Timestamp('today') - pd.tseries.offsets.MonthBegin(13)).strftime('%Y%m%d')
end_date = (pd.Timestamp('today') - pd.tseries.offsets.Day(1)).strftime('%Y%m%d')

df = pd.read_excel('藥品基本檔.xls')['藥品代碼'].tolist()
for code in df:
    capital = '0' if code[0].isnumeric() else code[0]
    sql = f"SELECT `drug`, SUM(`total`) AS `qty` FROM `consmp_{capital}` WHERE `drug` = '{code}' AND `date` >= '{start_date}'"
    df = pd.read_sql(sql, engine).rename(columns={'drug':'藥品代碼','qty':'年用量'})
df = pd.concat(dflist, axis=0, ignore_index=True).fillna(0)    

 

  1. 找出藥品的單價
bs = pd.read_excel('藥品基本檔.xls')[['藥品代碼','自費價','健保價']]
bs['價格'] = bs['健保價']
bs.loc[bs['健保價']=='0', '價格'] = bs['自費價']
bs = bs[['藥品代碼','價格']]
df = pd.merge(bs, df, on='藥品代碼', how='right')

藥品的單價,如果可以找到成本價更好,但是醫院藥局端無法得知成本價,只好用健保價或自費價

 

  1. 計算出每個藥品一年度的消耗總金額
df['消耗金額'] = df['年用量'] * df['價格']

 

  1. 將每個藥品一年度的消耗總金額依照大到小降冪排序
df = df.sort_values(by=['消耗金額'], ascending=False)

 

  1. 計算每個藥品的累加消耗金額
df['累進消耗金額'] = df['消耗金額'].cumsum()

 

  1. 計算所有藥品的總消耗金額
totalprice = df['消耗金額'].sum()

 

  1. 計算每個藥品的累加消耗金額比率 = 累加消耗金額 / 總消耗金額
df['累進消耗金額比率'] = df['累進消耗金額'] / totalprice

 

  1. 訂定 ABC 的分界
df.loc[df['累進消耗金額比率']<0.70, '分類'] = 'A'
df.loc[(df['累進消耗金額比率']>=0.70)&(df['累進消耗金額比率']<0.95), '分類'] = 'B'
df.loc[(df['累進消耗金額比率']>=0.95)&(df['累進消耗金額比率']<=1), '分類'] = 'C'

 

計算完成之後,可以輸出成 csv 檔,以供其他程式讀取。

df = df[['藥品代碼','分類']]
df.to_csv('abc.csv', index=False)

藥品 ABC 分類的應用與未來

目前我們以 ABC 分類法來決定購買的數量, A 類物品應該要嚴格控制庫存,舉例來說購買的數量可能為三天到七天的平均日用量,而 B 類可能為兩週用量, C 類為一個月或是三個月用量等,這個日後會再提及。

值得一想的是目前深度學習的風潮可能會逐漸改變傳統數學計算的分類,尤其是深度學習之中的非監督分群分類法,可能會分出比 ABC 還要更精確的庫存管理類別,這個也留待日後再來研究了。