解決したいこと
Python初学者ですが、学習のために既存プログラムの改修を行っております。
行いたい内容は、複数のcsvファイルを読み込み、データを整理した後、一つのファイルに書き出しです。
行いたい内容
共通の処理やまとまりを関数に分離する、定数化できるところは定数化する
「# CSVファイルを読み込んで辞書のリストで返す関数を実装する」の箇所で関数を用いて実行してみましたが、
下記のネームエラーが出てしまいます。
エラーでは、dataが定義されていないとのことですが、関数を呼び出している「# * 対象の月のデータのみ読み込み」
の引数に問題があるのでしょうか?
Traceback (most recent call last): File "/Users/******/docker/src/main.py", line 81, in <module> main() File "/Users/******/docker/src/main.py", line 55, in main for row in read_csv(data): NameError: name 'data' is not defined
ファイル等の情報
ファイルは下記になります。
商品のマスターデータ →/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を紐付け、紐付く商品名と商品価格を出力させます。
現在のプログラム
py
1import os 2import re 3 4ITEMS_DATA = 'input/items.csv' 5ITEMS_COLUMNS = ['item_id', 'name', 'price'] 6 7SALES_RAW_REGEX = re.compile(r'^sales_raw_(\d{4})(\d{2})(\d{2}).csv$') 8SALES_COLUMNS = ['purchase_id', 'user_id', 'item_id', 9 'item_name', 'item_price', 'amount', 'sold_at'] 10SALES_DATA = 'output/sales.csv' 11 12ENCODING = 'utf-8' 13CSV_INPUT = input('') 14 15# CSVファイルを読み込んで辞書のリストで返す関数を実装する 16def read_csv(f, columns): 17 with open(os.path.join('input/', filename), encoding=ENCODING) as f: 18 for row in f: 19 data = row.rstrip().split(',') 20 21# Step5では以下の状態で実装する 22def write_csv(f, data, columns): 23 pass 24 25# Step5では以下の状態で実装する 26def read_items(): 27 pass 28 29# Step5では以下の状態で実装する 30def read_sales_raw(target_year, target_month): 31 pass 32 33# Step5では以下の状態で実装する 34def write_sales(sales): 35 pass 36 37def main(): 38 # 商品のマスターデータ読み込み 39 items = {} 40 with open(ITEMS_DATA, encoding=ENCODING) as f: 41 # CSVファイルを読み込んで辞書のリストで返す関数使う 42 for row in f: 43 item_id, item_name, item_price = row.rstrip().split(',') 44 items[item_id] = { 45 'item_name': item_name, 46 'item_price': item_price 47 } 48 49 # 売上の生データを読み込んで、まとめる 50 sales = [] 51 for filename in os.listdir('input/'): 52 # * 対象の月のデータのみ読み込み 53 if re.match(CSV_INPUT, filename): 54 with open(os.path.join('input/', filename), encoding=ENCODING) as f: 55 for row in read_csv(f, data): 56 # 商品の情報を追加する 57 item_id = data[2] 58 if item_id in items: 59 sales.append({ 60 'purchase_id': data[0], 61 'user_id': data[1], 62 'item_id': data[2], 63 'item_name': items[item_id]['item_name'], 64 'item_price': items[item_id]['item_price'], 65 'amount': data[3], 66 'sold_at': data[4] 67 }) 68 69 # まとめた売上データを書き出し 70 m = SALES_RAW_REGEX.search(filename) 71 if len(sales) == 0: 72 print('書き出しファイルがありません') 73 return 74 SALES_COLUMNS 75 with open(SALES_DATA, mode='w', encoding=ENCODING) as f: 76 for row in sales: 77 row_str = ','.join(str(row[column]) for column in SALES_COLUMNS) 78 f.write(row_str + '\n') 79 80if __name__ == "__main__": 81 main()
改修途中のプログラム
py
1import os 2import re 3 4ITEMS_DATA = 'input/items.csv' 5ITEMS_COLUMNS = ['item_id', 'name', 'price'] 6 7SALES_RAW_REGEX = re.compile(r'^sales_raw_(\d{4})(\d{2})(\d{2}).csv$') 8SALES_COLUMNS = ['purchase_id', 'user_id', 'item_id', 9 'item_name', 'item_price', 'amount', 'sold_at'] 10SALES_DATA = 'output/sales.csv' 11 12ENCODING = 'utf-8' 13CSV_INPUT = input('') 14 15# CSVファイルを読み込んで辞書のリストで返す関数を実装する 16def read_csv(f, columns): 17 with open(os.path.join('input/', filename), encoding=ENCODING) as f: 18 for row in f: 19 data = row.rstrip().split(',') 20 21# Step5では以下の状態で実装する 22def write_csv(f, data, columns): 23 pass 24 25# Step5では以下の状態で実装する 26def read_items(): 27 pass 28 29# Step5では以下の状態で実装する 30def read_sales_raw(target_year, target_month): 31 pass 32 33# Step5では以下の状態で実装する 34def write_sales(sales): 35 pass 36 37def main(): 38 # 商品のマスターデータ読み込み 39 items = {} 40 with open(ITEMS_DATA, encoding=ENCODING) as f: 41 # CSVファイルを読み込んで辞書のリストで返す関数使う 42 for row in f: 43 item_id, item_name, item_price = row.rstrip().split(',') 44 items[item_id] = { 45 'item_name': item_name, 46 'item_price': item_price 47 } 48 49 # 売上の生データを読み込んで、まとめる 50 sales = [] 51 for filename in os.listdir('input/'): 52 # * 対象の月のデータのみ読み込み 53 if re.match(CSV_INPUT, filename): 54 with open(os.path.join('input/', filename), encoding=ENCODING) as f: 55 for row in read_csv(f, data): 56 # 商品の情報を追加する 57 data = row.rstrip().split(',') 58 item_id = data[2] 59 if item_id in items: 60 sales.append({ 61 'purchase_id': data[0], 62 'user_id': data[1], 63 'item_id': data[2], 64 'item_name': items[item_id]['item_name'], 65 'item_price': items[item_id]['item_price'], 66 'amount': data[3], 67 'sold_at': data[4] 68 }) 69 70 # まとめた売上データを書き出し 71 m = SALES_RAW_REGEX.search(filename) 72 if len(sales) == 0: 73 print('書き出しファイルがありません') 74 return 75 SALES_COLUMNS 76 with open(SALES_DATA, mode='w', encoding=ENCODING) as f: 77 for row in sales: 78 row_str = ','.join(str(row[column]) for column in SALES_COLUMNS) 79 f.write(row_str + '\n') 80 81if __name__ == "__main__": 82 main()
自分で試したこと
・繰り返し使用されるコードに関しては、定数を定義しました。
・必要な関数の処理のまとまりをコメントアウトで記載しました。
・自分でプログラムの編集を行いましたが、どうしても既存プログラムに引っ張られ、変更点があまり無い状況です。
基本的にモジュールの追加は行わず実装したいと思っております。
その他に何か必要な情報などありましたら、提示いたします。
長くなってしまい、大変恐縮ではございますが、ご教授頂けますと幸いです。
よろしくお願いいたします。
あなたの回答
tips
プレビュー