見出し画像

【プログラミング初心者】が売上を予測してみました (vol.1:データ整理編)

この記事は、週毎の売上分析、予測をまとめたものです。
内容は3部構成になっています。
vol.1 : データ整理編
vol.2 : 時系列解析編
vol.3 : 回帰編

今回は「vol.1 : データ整理編」です。

はじめに

はじめに、なぜこのようなデータ分析をしてみようと思ったのか、少しお話しさせてください。
私はアパレル業界で働いています。
近年アパレル業界の過剰在庫や廃棄量の増加が環境汚染につながるというニュースを目にすることがあります。供給者としては100%消化を目指しているのですが、天候や環境の変化、デザインとお客様の気分のミスマッチ、色数・生産枚数が多かったなど、さまざまな理由で在庫が残ることがあります。デザイナーさん、生地屋さん、工場さん、いろんな方の協力を経て出来上がった洋服が、お客様の手に渡ることなく在庫として残っているのを見るととても心が痛みます。
 1枚でも倉庫に残る在庫を少なくするにはどうするか、、「未来の売上を予測できれば、在庫が残らず適量を生産できるかもしれない」と思い、今回全くの初心者ですが、プログラミングの勉強を始めました。
まだまだ実務に使える精度にはなっていないのですが、今後さらにデータを加えていくことで売上予測の精度を上げたいです。そして売上予測を在庫管理に活用し、売上向上とともに過剰在庫を削減することが私の目標です。

私の環境

Python3
MacBook Pro
ChromeGoogle Colaboratory

売上データの中身

期間:2018年~2020年
店舗数:11店舗

私のレベル

プログラミング初心者
アイデミープレミアムプラン「データ分析コース(6ヶ月)」学習中


【データクレンジング・成形】


excelデータの読み込み

まずは2018年から2020年までの3年分の週毎の売上データを読み込んでいきます。
試しに2018年度 MD1週のデータを表示します。

import pandas as pd
filepass="2018年度売上週報/MD1週売上週報.xlsx"
df= pd.read_excel("/content/drive/MyDrive/2018年度売上週報/MD1週売上週報.xlsx")
df.head()

スクリーンショット 2021-03-23 17.07.56

箇所を指定して再度表示します。

df2=df[293:]
df2

スクリーンショット 2021-03-19 20.59.00

AからKまでの11店舗のデータだけを抽出します。

targetname=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
columns_name=df2.columns[1]
df2.columns=["Unnamed: 0", "tar",	"Unnamed: 2",	"MD1週",	"週実績",	"Unnamed: 5",	"Unnamed: 6",	"Unnamed: 7",	"Unnamed: 8",	"Unnamed: 9"]
df2= df2.query("tar in @targetname")
df2

スクリーンショット 2021-03-19 21.00.11

1列目は不要なので、削除します。

df3=df2.drop("Unnamed: 0", axis=1)
df3

スクリーンショット 2021-03-19 21.01.05

11店舗の週実績の列のみを取り出します。

df = pd.DataFrame(columns=['MD週','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'])
df.loc[0,:]=[filepass.split("年")[0]+filepass.split("/")[1].split("週売")[0]]+list(df3.loc[:,"週実績"])
df

スクリーンショット 2021-03-19 21.02.04

続けて2018年MD2週目以降、2019、2020年度の売上データも読み込んでいきます。​

import glob
targetfolder=["2018年度売上週報", "2019年度売上週報", "2020年度売上週報"]
df_all = pd.DataFrame(columns=['MD週','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'])
counter=0
targetname=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
for folder in targetfolder:
 targetfiles=glob.glob(folder +"/*.xlsx")
 print(targetfiles)
 for filename in targetfiles:
   filepass=filename
   print(filepass)
   df= pd.read_excel(filepass)
   df2=df[280:]
   try:
     df2.columns=["Unnamed: 0", "tar", "Unnamed: 2", "MD1週", "週実績",  "Unnamed: 5", "Unnamed: 6", "Unnamed: 7", "Unnamed: 8", "Unnamed: 9"]
   except:
     df2.columns=["Unnamed: 0", "tar", "Unnamed: 2", "MD1週", "週実績",  "Unnamed: 5", "Unnamed: 6", "Unnamed: 7", "Unnamed: 8", "Unnamed: 9", "Unnamed: 10"]
   df2= df2.query("tar in @targetname")
   df3=df2.drop("Unnamed: 0", axis=1)
   df_all.loc[counter,:]=[filepass.split("年")[0]+filepass.split("/")[1].split("週売")[0]]+list(df3.loc[:,"週実績"])
   counter+=1

データ読み込み前のデータ整形が不十分だったので、読み込み中に何度もエラーしてしまいました。そのたびに修正をして、なんとか全て読み込むことができました。

並べ替え

抜けている部分がないか確認するため、ソートで昇順に並べ替えます。

df_all.sort_values(by="MD週")

スクリーンショット 2021-03-19 21.04.13

2018年MD1週の次は2週が来るはずですが、10週になってしまっています。

欠損値の確認

昇順に並べ替えをしつつ、欠損値を確認します。

import glob
targetfolder=["2018年度売上週報", "2019年度売上週報", "2020年度売上週報"]
df_all = pd.DataFrame(columns=['MD週','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'])
counter=0
targetname=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
for folder in targetfolder:
 #targetfiles=glob.glob(folder +"/*.xlsx")
 #print(targetfiles)
 for num in range(53):
   filepass=folder+"/MD{}週売上週報.xlsx".format(num)
   try:
       df= pd.read_excel(filepass)
       print(filepass)
       df2=df[280:]
       try:
         df2.columns=["Unnamed: 0", "tar", "Unnamed: 2", "MD1週", "週実績",  "Unnamed: 5", "Unnamed: 6", "Unnamed: 7", "Unnamed: 8", "Unnamed: 9"]
       except:
         df2.columns=["Unnamed: 0", "tar", "Unnamed: 2", "MD1週", "週実績",  "Unnamed: 5", "Unnamed: 6", "Unnamed: 7", "Unnamed: 8", "Unnamed: 9", "Unnamed: 10"]
       df2= df2.query("tar in @targetname")
       df3=df2.drop("Unnamed: 0", axis=1)
       df_all.loc[counter,:]=[filepass.split("年")[0]+filepass.split("/")[1].split("週売")[0]]+list(df3.loc[:,"週実績"])
       counter+=1
   except:
       print("/MD{}週売上週報 はありませんでした".format(num))
/MD0週売上週報 はありませんでした
2018年度売上週報/MD1週売上週報.xlsx
2018年度売上週報/MD2週売上週報.xlsx
2018年度売上週報/MD3週売上週報.xlsx
2018年度売上週報/MD4週売上週報.xlsx
2018年度売上週報/MD5週売上週報.xlsx
/MD6週売上週報 はありませんでした
...  ...  ...  ...  ...  ...  ...  ...  ...  ...
2020年度売上週報/MD47週売上週報.xlsx
2020年度売上週報/MD48週売上週報.xlsx
/MD49週売上週報 はありませんでした
2020年度売上週報/MD50週売上週報.xlsx
2020年度売上週報/MD51週売上週報.xlsx
2020年度売上週報/MD52週売上週報.xlsx

29週分の欠損がありました。
csvデータに変換してから、欠損値を補完していきます。

df_all.to_csv("df_all.csv")

欠損値の補完

csvデータを読み込みます。

import pandas as pd
df= pd.read_csv("/content/drive/MyDrive/df_all.csv", index_col=0)

欠損値を補完するため、各列ごとに平均や標準偏差、最大値、最小値、最頻値などの要約統計量を取得します。

df.describe()

スクリーンショット 2021-03-19 21.08.50

今回は平均値で補完します。

mean_data=df.describe().loc["mean"]
mean_data
A 84231.928571
B 52154.087302
C 28478.031746
D 5664.420635
E 9020.976190
F 22272.952381
G 29451.595238
H 32868.920635
I 45465.682540
J 5869.007937
K 5265.373016
Name: mean, dtype: float64

小数点以下は不要なため、整数のみを取得します。

for i in mean_data.index:
 mean_data[i]=int(mean_data[i])

mean_data=mean_data.astype(int)
mean_data
A 84231
B 52154
C 28478
D 5664
E 9020
F 22272
G 29451
H 32868
I 45465
J 5869
K 5265
Name: mean, dtype: int64

欠損している部分に平均値を補完します。

import glob
targetfolder=["2018", "2019", "2020"]
new_df = pd.DataFrame(columns=['MD週','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'])
counter=0
targetname=['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K']
for folder in targetfolder:
 #targetfiles=glob.glob(folder +"/*.xlsx")
 #print(targetfiles)
 for num in range(1, 53):
   tmp=folder+ "MD"+ str(num)
   data=df.query("MD週==@tmp")
   if len(data) == 0:
     new_df.loc[counter,:]= [tmp]+ list(mean_data)
   else:
     new_df.loc[counter,:]= data.values
   counter+=1
new_df

スクリーンショット 2021-03-19 21.09.50

csvデータの作成

csvデータに変換します。

new_df.to_csv("/content/drive/MyDrive/new_df.csv")

無事にデータが作成できました!!


今回初めてデータの収集を自分で行いました。必要なデータを揃えるのに、約10時間、データの整形に約10時間かかりました。
データの読み込みでは、すべてのデータの行や列、名前が一致していないので(途中から項目が増えるなど)、たびたびエラーがおきてしまいました。
アイデミープレミアムプランの講座でも、データ整理の部分に多くの時間がかかることが書かれていましたが、ほんとうにその通りだと実感しました。
次回からは、データの読み込みを始める前に、ある程度データの中身を確認し、あらかじめ整えておくようにしたいと思います。

最後まで読んでいただき、ありがとうございます。「vol.1 : データ整理編」はこちらで終わりです。
続きは「vol.2 : 時系列解析編」です。こちらもぜひご覧くださいませ。

この記事が気に入ったらサポートをしてみませんか?