某POSシステムから取り出したデータを処理して商品・時間別の集計表を作る

# はじめに

数人の知人から「POSから取り出したデータが扱いにくいので集計して下さい」との依頼を受けたので、Pythonで扱いやすいデータに変換するスクリプトを作ってみました。

# 受け取ったデータを確認

テキストエディタで開いて確認してみる。

```csv:zitem.csv
0000,0000,0000,20160000,201600000000,1000
メニューコード／ＰＬＵコード,自社コード,商品名称,商品区分,商品区分名称,サブ/セット/コメント 親メニューコード,親メニュー名称,単価,フリー１集計コード,フリー１集計名称,フリー２集計コード,フリー２集計名称,フリー３集計コード,フリー３集計名称,テイクアウト区分,テイクアウト区分名称,原単価,ＧＰコード,ＧＰ名称,ＤＰコード,ＤＰ名称,時間帯開始時間,時間帯終了時間,時間帯０１出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０２出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０３出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０４出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０５出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０６出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０７出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０８出数（点数）,時間帯開始時間,時間帯終了時間,時間帯０９出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１０出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１１出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１２出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１３出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１４出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１５出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１６出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１７出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１８出数（点数）,時間帯開始時間,時間帯終了時間,時間帯１９出数（点数）,時間帯開始時間,時間帯終了時間,時間帯２０出数（点数）,時間帯開始時間,時間帯終了時間,時間帯２１出数（点数）,時間帯開始時間,時間帯終了時間,時間帯２２出数（点数）,時間帯開始時間,時間帯終了時間,時間帯２３出数（点数）,時間帯開始時間,時間帯終了時間,時間帯２４出数（点数）,エンプロイ出数,プロモーション出数,商品別データ１,商品別データ２,商品別データ３,時間帯０１ 値割引　点数,時間帯０１ 値割引　金額,時間帯０１ プロモ　出数,時間帯０１ 予備,時間帯０２ 値割引　点数,時間帯０２ 値割引　金額,時間帯０２ プロモ　出数,時間帯０２ 予備,時間帯０３ 値割引　点数,時間帯０３ 値割引　金額,時間帯０３ プロモ　出数,時間帯０３ 予備,時間帯０４ 値割引　点数,時間帯０４ 値割引　金額,時間帯０４ プロモ　出数,時間帯０４ 予備,時間帯０５ 値割引　点数,時間帯０５ 値割引　金額,時間帯０５ プロモ　出数,時間帯０５ 予備,時間帯０６ 値割引　点数,時間帯０６ 値割引　金額,時間帯０６ プロモ　出数,時間帯０６ 予備,時間帯０７ 値割引　点数,時間帯０７ 値割引　金額,時間帯０７ プロモ　出数,時間帯０７ 予備,時間帯０８ 値割引　点数,時間帯０８ 値割引　金額,時間帯０８ プロモ　出数,時間帯０８ 予備,時間帯０９ 値割引　点数,時間帯０９ 値割引　金額,時間帯０９ プロモ　出数,時間帯０９ 予備,時間帯１０ 値割引　点数,時間帯１０ 値割引　金額,時間帯１０ プロモ　出数,時間帯１０ 予備,時間帯１１ 値割引　点数,時間帯１１ 値割引　金額,時間帯１１ プロモ　出数,時間帯１１ 予備,時間帯１２ 値割引　点数,時間帯１２ 値割引　金額,時間帯１２ プロモ　出数,時間帯１２ 予備,時間帯１３ 値割引　点数,時間帯１３ 値割引　金額,時間帯１３ プロモ　出数,時間帯１３ 予備,時間帯１４ 値割引　点数,時間帯１４ 値割引　金額,時間帯１４ プロモ　出数,時間帯１４ 予備,時間帯１５ 値割引　点数,時間帯１５ 値割引　金額,時間帯１５ プロモ　出数,時間帯１５ 予備,時間帯１６ 値割引　点数,時間帯１６ 値割引　金額,時間帯１６ プロモ　出数,時間帯１６ 予備,時間帯１７ 値割引　点数,時間帯１７ 値割引　金額,時間帯１７ プロモ　出数,時間帯１７ 予備,時間帯１８ 値割引　点数,時間帯１８ 値割引　金額,時間帯１８ プロモ　出数,時間帯１８ 予備,時間帯１９ 値割引　点数,時間帯１９ 値割引　金額,時間帯１９ プロモ　出数,時間帯１９ 予備,時間帯２０ 値割引　点数,時間帯２０ 値割引　金額,時間帯２０ プロモ　出数,時間帯２０ 予備,時間帯２１ 値割引　点数,時間帯２１ 値割引　金額,時間帯２１ プロモ　出数,時間帯２１ 予備,時間帯２２ 値割引　点数,時間帯２２ 値割引　金額,時間帯２２ プロモ　出数,時間帯２２ 予備,時間帯２３ 値割引　点数,時間帯２３ 値割引　金額,時間帯２３ プロモ　出数,時間帯２３ 予備,時間帯２４ 値割引　点数,時間帯２４ 値割引　金額,時間帯２４ プロモ　出数,時間帯２４ 予備
0000000000000,0000000000000,サンプル１          ,00,メイン  ,0000,                    ,+001200,01,フリー１            ,01,フリー２            ,01,フリー３            ,0,店内飲食,+000000,01,食事                ,01,水                  ,0000,0059,+0000,0100,0159,+0000,0200,0259,+0000,0300,0359,+0000,0400,0459,+0000,0500,0559,+0000,0600,0659,+0000,0700,0759,+0000,0800,0859,+0000,0900,0959,+0000,1000,1059,+0000,1100,1159,+0000,1200,1259,+0000,1300,1359,+0000,1400,1459,+0000,1500,1559,+0000,1600,1659,+0000,1700,1759,+0002,1800,1859,+0000,1900,1959,+0000,2000,2059,+0000,2100,2159,+0000,2200,2259,+0000,2300,2359,+0000,+0000,+0000,+0000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000
0000000000000,0000000000000,テスト サンプル   ,00,メイン  ,0000,                    ,+000400,01,フリー１            ,01,フリー２            ,01,フリー３            ,0,店内飲食,+000000,01,食事                ,01,水                  ,0000,0059,+0000,0100,0159,+0000,0200,0259,+0000,0300,0359,+0000,0400,0459,+0000,0500,0559,+0000,0600,0659,+0000,0700,0759,+0000,0800,0859,+0000,0900,0959,+0000,1000,1059,+0000,1100,1159,+0000,1200,1259,+0000,1300,1359,+0000,1400,1459,+0000,1500,1559,+0000,1600,1659,+0000,1700,1759,+0000,1800,1859,+0000,1900,1959,+0000,2000,2059,+0000,2100,2159,+0000,2200,2259,+0000,2300,2359,+0000,+0000,+0000,+0000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000,+0000,+0000000,+0000,+0000
（以下、略）
```

...確かにこれをそのまま使うのは厳しい(-_-;)

データの内容や要望について少し聞いてみると、
- メニューコードは13桁あるけど0〜9999を使用している
- メニューコードを設定していても販売しなかった商品名はCSVには含まれない
- 0時〜23時までの商品別の販売数が欲しい
- このファイルは1日ごとに出力され、毎日作成する
- 最終的には複数日のファイルを結合させたい

# 出力CSVのデータ形式

ヘッダーはメニューコードと商品名、単価として、以降時間ごとに出た商品の数を整理します。

```csv:output.csv
メニューコード,0,1,2,〜,9999
商品名称,サンプル1,サンプル2,サンプル3,〜,サンプル10000
単価,100,200,300,〜10000
2016/1/1 0:00,1,2,3,〜,10
2016/1/1 1:00,4,5,6,〜,0
2016/1/1 2:00,6,2,9,〜,20
(中略)
2016/1/1 23:00,1,2,3,〜,10
```

# ライブラリの読み込み

```py:
import pandas as pd
import os
import datetime
```

# ファイルの読み込み

ファイル名が固定とのことなので、ファイル名を設定し、作成日から日付のデータを取得して読み込む。

```py:
# ファイル名
filename = "zitem.csv"    

# 日付データ取得
dt = datetime.datetime.fromtimestamp(os.stat(filename).st_mtime)
y = dt.year
m = dt.month
d = dt.day

# データ読み込み
df = pd.read_csv(filename,encoding="SHIFT-JIS",skiprows=1)
```

# 商品名と価格を取得

商品名と価格について、CSVのデータに入っている時と入っていない時があるとのことなので、今後複数のデータをまとめることを考慮し、とりあえず枠を用意しておいてデータがある部分を埋めていくことにする。

```py:
cnt = 10001

names = [""] * cnt
prices = [0] * cnt

for i in range(len(df)):
    key = int(df.loc[i][0]) + 1
    names[key] = df.loc[i][2]
    prices[key] = int(df.loc[i][7])
```

0〜9999なので、10000種類のデータなのですが、日時データを付与するので10001個のデータ配列にしてます。

# 販売数を取得

23列目から3列ごとに販売数のデータが入っているようなので、24時間分のデータを3列ごとに取得する。

```py:
x = 23

datas = []

for i in range(24):
    items = [0] * cnt
    items[0] = datetime.datetime(y,m,d,i,0).strftime("%Y-%m-%d %H:%M")
    for j in range(len(df)):
        key = df.loc[j][0] + 1
        num = int(df.loc[j][x])
        items[key] = num
    datas.append(items)
    x += 3
```

# ファイル出力

取得した情報をCSVファイルに保存。

```py:
f = open('output.csv', 'w')

sName = ""
sPrice = ""

for i in range(len(names)):
    sName += names[i] + ","
    sPrice += str(prices[i]) + ","

f.write(sName + "\n" + sPrice + "\n")

for i in range(len(datas)):
    data = datas[i]
    sData = ""
    for j in range(len(data)):
        sData += str(data[j]) + ","
    f.write(sData + "\n")
    
f.close()
```

ここまでのコードを「pos.py」として保存し、実行。

```sh:
$ python pos.py
```

できた！

# 全ソースコード掲載

```py:pos.py
import pandas as pd
import os
import datetime

# ファイル名
filename = "zitem.csv"    

# 日付データ取得
dt = datetime.datetime.fromtimestamp(os.stat(filename).st_mtime)
y = dt.year
m = dt.month
d = dt.day

# データ読み込み
df = pd.read_csv(filename,encoding="SHIFT-JIS",skiprows=1)

# 必要なデータを取得

cnt = 10001

names = [""] * cnt
prices = [0] * cnt

for i in range(len(df)):
    key = int(df.loc[i][0]) + 1
    names[key] = df.loc[i][2]
    prices[key] = int(df.loc[i][7])

x = 23

datas = []

for i in range(24):
    items = [0] * cnt
    items[0] = datetime.datetime(y,m,d,i,0).strftime("%Y-%m-%d %H:%M")
    for j in range(len(df)):
        key = df.loc[j][0] + 1
        num = int(df.loc[j][x])
        items[key] = num
    datas.append(items)
    x += 3

# ファイル出力

f = open('output.csv', 'w')

sName = ""
sPrice = ""

for i in range(len(names)):
    sName += names[i] + ","
    sPrice += str(prices[i]) + ","

f.write(sName + "\n" + sPrice + "\n")

for i in range(len(datas)):
    data = datas[i]
    sData = ""
    for j in range(len(data)):
        sData += str(data[j]) + ","
    f.write(sData + "\n")
    
f.close()
```

# さいごに

きっともっといい方法があるに違いない！