はじめに
飲食業界は、常に変化し続ける市場環境や顧客の嗜好に対応するため、データ分析の重要性がますます高まっています。データを適切に活用することで、売上の向上や顧客満足度の向上、新たなビジネスチャンスの発見など、多くの利点を享受することができます。今回は飲食店の練習データを用いてデータ分析を行っていきます。
開発環境と使用データ
開発環境はGoogle Colabで実装していきます。
3種類のデータを分析に使用します。
決済データ、オーダーデータ、人件費データ
今回求めたいこと
・月ごとの売上、粗利額、人件費、営業利益額
・月ごと、曜日別の顧客単価、客数(大人、子供、合計)アンケート回答率、リピート率、滞在時間、商品カテゴリ別の売上、カテゴリ別の注文率
・顧客のリピート率と注文カテゴリの関係
補足
・原価率
フード/ワイン:35%、上記以外:25%
・販売管理費
人件費以外の固定費:33万/月、人件費以外の変動費:売上の10%
実装
pandasのみを使用してデータ分析をしました。
from google.colab import drive
drive.mount("/content/drive/")
import pandas as pd
#expense:人件費データ,order:オーダーデータ,account:決済データ
expense = pd.read_csv("/content/drive/yourpath")
order = pd.read_csv("/content/drive/yourpath")
account = pd.read_csv("/content/drive/yourpath")
order = order.groupby(["決済ID","カテゴリ"])[["総売上高","数量"]].sum()
#注文開始時間を%H%Mに変換
account["注文開始時間"] = pd.to_datetime(account["注文開始時間"]).dt.strftime("%H%M").astype(int)
account.head()
#時間ごとに午前、昼、午後に分ける
def classify_day(dt):
if dt < 1200:
return "午前"
elif 1200 <= dt < 1330:
return "昼"
else:
return "午後"
account["時刻区分"] = account["注文開始時間"].apply(classify_day)
account = account.groupby(["決済ID","日付","注文開始時間","滞在時間","時刻区分","来店数アンケート"])[["大人","子供"]].sum
#account,orderを結合
ao = pd.merge(account,order,how = "left",on = "決済ID")
#出勤日を%Y-%mの形に変換し、年月ごとにgroupby
expense["出勤日"] = pd.to_datetime(expense["出勤日"])
expense["年月"] = expense["出勤日"].dt.strftime("%Y-%m")
pe = expense.groupby("年月")[["人件費合計"]].sum()
ao["日付"] = pd.to_datetime(ao["日付"])
ao["年月"] = ao["日付"].dt.strftime("%Y-%m")
pf = ao.groupby(["決済ID","年月"])[["総売上高"]].sum()
#aoで原価をそれぞれ求める
ao["原価1"] = ao.loc[(ao["カテゴリ"] == "フード") | (ao["カテゴリ"] == "ワイン")]["総売上高"] * 0.35
ao["原価2"] = ao.loc[(ao["カテゴリ"] == "ドリンク") | (ao["カテゴリ"] == "デザート") | (ao["カテゴリ"] == "コーヒー") | (ao["カテゴリ"] == "その他")]["総売上高"] * 0.25
ao = ao.fillna({"原価1":0})
ao = ao.fillna({"原価2":0})
ao["原価"] = ao["原価1"] + ao["原価2"]
ao = ao.drop(["原価1","原価2"],axis = 1)
#月ごとの原価を求め、それとpfを結合する
gp = ao.groupby(["年月"])[["原価"]].sum()
gp = pd.merge(pf,gp,how = "right",on = "年月")
gp["粗利額"] = gp["総売上高"] - gp["原価"]
#pfとpe(月ごとの人件費)を結合し、営業利益額を求める
op = pd.merge(pf,pe,how = "left",on = "年月")
op["粗利額"] = gp["粗利額"]
op["営業利益額"] = op["粗利額"] - (op["人件費合計"] + 330000 + op["総売上高"] * 0.1)
#月ごとの人件費の平均を求める
pem = expense.groupby("年月")[["人件費合計"]].mean()
#月ごとの総売上高の平均を求める
pfd = ao.groupby("日付")[["総売上高"]].sum()
pfd = pfd.reset_index()
pfd["年月"] = pfd["日付"].dt.strftime("%Y-%m")
pfd = pfd.groupby("年月")[["総売上高"]].mean()
#月ごとの原価の平均を求める
gpd = ao.groupby("日付")[["原価"]].sum()
gpd = gpd.reset_index()
gpd["年月"] = gpd["日付"].dt.strftime("%Y-%m")
gpd = gpd.groupby("年月")[["原価"]].mean()
d = ao.groupby("日付")[["総売上高"]].sum()
d = d.reset_index()
d["年月"] = d["日付"].dt.strftime("%Y-%m")
lists = []
for t in d["年月"].unique():
a = len(d.loc[d["年月"] == t])
lists.append(a)
#一日当たりの傾向を求めるため、営業利益額を日付で割る
op["日数"] = lists
op["一日の売り上げ"] = pfd
op["一日の人件費"] = pem
op["一日の粗利額"] = gpd
op["一日の営業利益額"] = op["営業利益額"] /lists
#月ごとの客人数
ao["客人数"] = ao["大人"] + ao["子供"]
cus = ao.groupby("年月")[["大人","子供","客人数"]].sum()
cus["単価"] = op["総売上高"] / cus["客人数"]
years = ao["年月"].unique()
lists = []
#アンケート回答率
for y in years:
a = ao.loc[ao["年月"] == y]
b = (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2])) / len(a)
lists.append(b)
cus["アンケート回答率"] = lists
lists = []
for y in years:
a = ao.loc[ao["年月"] == y]
b = len(a[a["来店数アンケート"] == 2]) / (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2]))
lists.append(b)
cus["リピート率"] = lists
#月ごとの滞在時間
time = ao.groupby("年月")[["滞在時間"]].mean()
cus["滞在時間"] = time
order = ao.groupby(["年月","カテゴリ"])[["総売上高"]].sum()
order = order.rename(columns = {"総売上高":"カテゴリ別売上"})
#月ごとのカテゴリ別売上
pfuni = pf["総売上高"].unique()
lists = [uni for uni in pfuni for _ in range(6)]
len(lists)
order["総売上高"] = lists
order["注文率"] = order["カテゴリ別売上"] / order["総売上高"]
order = order.drop(["総売上高"],axis = 1).reset_index()
#曜日を定義
ao["曜日"] = ao["日付"].dt.day_name()
week = ["Monday", 'Tuesday','Wednesday','Thursday','Friday', 'Saturday', 'Sunday']
#曜日ごとの重要指標A
wk = ao.groupby(["日付","曜日"])[["大人","子供","客人数","総売上高"]].sum().reset_index()
wk = wk.groupby("曜日")[["大人","子供","客人数","総売上高"]].mean()
wk = wk.reindex(index = week)
wk["顧客単価"] = wk["総売上高"] / wk["客人数"]
weeks = ao["曜日"].unique()
lists = []
for w in weeks:
a = ao.loc[ao["曜日"] == w]
b = (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2])) / len(a)
lists.append(b)
wk["アンケート回答率"] = lists
lists = []
for w in weeks:
a = ao.loc[ao["曜日"] == w]
b = len(a[a["来店数アンケート"] == 2]) / (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2]))
lists.append(b)
wk["リピート率"] = lists
hour = ao.groupby(["曜日"])[["滞在時間"]].mean()
wk = pd.merge(wk,hour,how = "left",on = "曜日")
#曜日ごとのカテゴリ別売上
wkc = ao.groupby(["日付","カテゴリ","曜日"])[["総売上高"]].sum()
wkc = wkc.groupby(["曜日","カテゴリ"])[["総売上高"]].mean()
wkc = wkc.rename(columns = {"総売上高":"カテゴリ別売上"})
wkc = wkc.reindex(week,level = "曜日")
wkp = wk["総売上高"].unique()
lists = [a for a in wkp for _ in range(6)]
wkc["総売上高"] = lists
wkc["注文率"] = wkc["カテゴリ別売上"] / wkc["総売上高"]
wkc = wkc.drop(["総売上高"],axis = 1)
#曜日別の総売上高、客人数
wp = ao.groupby(["日付","曜日"])[["総売上高"]].sum()
wp = wp.groupby("曜日")[["総売上高"]].mean()
wp = wp.reindex(index = week)
wp["客人数"] = ao.groupby("曜日")[["客人数"]].sum()
#午前昼午後別の重要指標A
cd = ao.groupby(["日付","時刻区分"])[["大人","子供","客人数","総売上高"]].sum()
cd = cd.groupby("時刻区分")[["大人","子供","客人数","総売上高"]].mean()
cd["顧客単価"] = cd["総売上高"] / cd["客人数"]
lists = []
for t in ao["時刻区分"].unique():
a = ao.loc[ao["時刻区分"] == t]
b = (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2])) / len(a)
lists.append(b)
cd["アンケート率"] = lists
lists = []
for t in ao["時刻区分"].unique():
a = ao.loc[ao["時刻区分"] == t]
b = len(a[a["来店数アンケート"] == 2]) / (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2]))
lists.append(b)
cd["リピート率"] = lists
t = ao.groupby("時刻区分")[["滞在時間"]].mean()
cd = pd.merge(cd,t,how = "left",on = "時刻区分")
#午前昼午後別のカテゴリ別売上
cc = ao.groupby(["時刻区分","カテゴリ"])[["総売上高"]].mean()
cc = cc.rename(columns = {"総売上高":"カテゴリ別売上"}).reset_index()
tc = cc.groupby("時刻区分")[["カテゴリ別売上"]].sum().reset_index()
lists = []
for h in cc["時刻区分"].unique():
a = len(cc.loc[cc["時刻区分"] == h])
lists.append(a)
t = []
for i,tu in zip(lists,tc["カテゴリ別売上"].unique()):
a = [tu] * i
t = t + a
cc["総売上高"] = t
cc["注文率"] = cc["カテゴリ別売上"] / cc["総売上高"]
cd = cd.drop(["総売上高"],axis = 1)
cc = cc.drop(["総売上高"],axis = 1)
cc = cc.groupby(["時刻区分","カテゴリ"])[["カテゴリ別売上","注文率"]].sum()
ao.groupby("カテゴリ")[["来店数アンケート"]].sum()
lists = []
for c in ao["カテゴリ"].unique():
a = ao.loc[ao["カテゴリ"] == c]
b = len(a[a["来店数アンケート"] == 2]) / (len(a[a["来店数アンケート"] == 1]) + len(a[a["来店数アンケート"] == 2]))
lists.append(b)
rc = pd.DataFrame(index = ao["カテゴリ"].unique(),
data = lists)
rc = rc.rename(columns = {0:"リピート率"})
まとめ
今回は飲食店のデータ分析を実装しました。
今後、実際の業務で飲食店のデータ分析をする機会があったら是非参考にしてみてください。