【Python3】csvファイル 売上データの集計・書き出しについて
解決したいこと
Python初学者ですが、学習のために既存プログラムの改修を行いたいと考えております。
行いたい内容は、複数のcsvファイルを読み込み、データを整理した後、一つのファイルに書き出しです。
*ページ下部に現状や問題点など記載しております。
ファイルは下記になります。
商品のマスターデータ
→/input/items.csv
商品の売上データ(日毎に別ファイル)
→/input/sales_raw_20161030.csv
/input/sales_raw_20161101.csv
...
/input/sales_raw_20161106.csv
書き出し後の売上データ
→/output/sales.csv
商品マスターデータ(items.csv)の中身は下記になります。
商品ID、商品名、商品価格
商品の売上データ(sales_raw_YYYYmmdd.csv)の中身は下記になります。
購入ID、ユーザーID、商品ID、個数、販売日時
書き出し後のデータ(sales.csv)は下記になります。
購入ID、ユーザーID、商品ID、商品名、商品価格、個数、販売日時
*商品の売上データの商品IDと商品マスターデータの商品IDを紐付け、紐付く商品名と商品価格を出力させます。
既存のプログラム
import os
def main():
with open('output/sales.csv', mode='w', encoding='utf-8') as sales_f:
for name in os.listdir('input/'):
if name.startswith('sales_raw_') and name.endswith('.csv') \
and "201611" in name:
with open(os.path.join('input/', name), encoding='utf-8') as f:
for row in f:
data = row.rstrip().split(',')
with open('input/items.csv', encoding='utf-8') as items_f:
for row in items_f:
data2 = row.rstrip().split(',')
if data2[0] == data[2]:
sales_f.write(
','.join((
data[0],
data[1],
data[2],
data2[1],
data2[2],
data[3],
data[4],
)) + '\n'
)
if __name__ == "__main__":
main()
既存プログラムの良く無い点は下記になります。
・全てのブロックが入れ子になっている
・一度に覚えておくべき変数が多い
・変数が何を意味しているのかが分かりにくい
・売上生データを1行1行処理するforループの中で、商品マスターデータファイルを読み込んでいるのも問題
・売上生データの行数の数だけ商品マスターデータファイルが開かれて、閉じられている。プログラムの動作としても無駄が多い。
改修途中のプログラム
import os
def main():
# 商品マスターデータの読み込み処理
items = {}
with open('input/items.csv', encoding='utf-8') as f:
for row in f:
data = row.rstrip().split(',')
item_id = data[0]
name = data[1]
price = data[2]
items[item_id] = {
'name': name,
'price': price
}
# 売上データの書き出し処理
with open('output/sales.csv', mode='w', encoding='utf-8') as sales_f:
for name in os.listdir('input/'):
if name.startswith('sales_raw_') and name.endswith('.csv') \
and "201611" in name:
with open(os.path.join('input/', name), encoding='utf-8') as f:
for row in f:
data = row.rstrip().split(',')
item_id = data[2]
if item_id in items:
sales_f.write(
','.join((
data[0],
data[1],
data[2],
items[item_id]['name'],
items[item_id]['price'],
data[3],
data[4],
)) + '\n'
)
if __name__ == "__main__":
main()
自分で試したこと
必要なコードのまとまりを設計しました。
・対象の年月の売上生データを読み込む処理の「まとまり」
・商品マスターデータを読み込む処理の「まとまり」
・商品IDから商品(商品名、商品価格)を取得する処理の「まとまり」
・売上データを作成する処理の「まとまり」
・売上データを書き出す処理の「まとまり」
終わっている処理
Step1
・input/items.csvを読み込んでいるwith文を分離する
・「商品マスターデータ」を後で使いやすい形にしておく
終わっていない処理
Step2
・入れ子の処理を分割する
・Step1のプログラムを「目的のデータを作る処理」と「ファイルに書き出す処理」に分離する
現状
Step1の改修を終えている状況になります。
Step2のデータ作成処理と書き出す処理の違いわからず、どのように改修すれば良いのか詰まっている状況になります。
また、入れ子の処理を分割では、売上データの書き出し処理のwith文の中にwith文が入っているので、この箇所を分割するのかなと思うのですが、どのように分割すると良いのかイメージが付かない状況になります。
Step2で終わりではありませんが、とりあえず目先の躓いている問題を解決したいと思っております。
その他に何か必要な情報などありましたら、提示いたします。
長くなってしまい、大変恐縮ではございますが、ご教授頂けますと幸いです。
よろしくお願いいたします。