テキストとしての表
CSV(カンマ区切り値)ファイルは、表をテキストで保存します。1行が1レコード、セルはカンマで区切られ、たいてい列名を示すヘッダー行が付きます。価格履歴、約定一覧、ほとんどのツールのエクスポートがこの形式です。line.split(",") で簡単に解析できそうですが、セル自体にカンマが含まれることがあり、その場合は引用符で囲まれます:AAPL,"Q3, adjusted"。手作業の分割ではここで壊れるので、標準の csv モジュールを使い、セル内の改行を正しく扱えるようファイルは newline="" で開きます。
import csv
# Write a small table with csv.writer
with open("prices.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.writer(file)
writer.writerow(["date", "symbol", "close", "note"])
writer.writerow(["2025-01-02", "AAPL", 184.25, "Q3, adjusted"])
writer.writerow(["2025-01-03", "AAPL", 185.5, ""])
# The comma inside the note is quoted for us
with open("prices.csv", encoding="utf-8") as file:
print(file.read().splitlines()[1]) # 2025-01-02,AAPL,184.25,"Q3, adjusted"行を読む
csv.reader(file) は各行を文字列のリストとして返します。csv.DictReader(file) は先にヘッダーを読み、各行を列名をキーとする辞書として返すので、読みやすく、列の順序が変わっても壊れません。どちらの場合も各セルは文字列なので、計算の前に float(...) や int(...) で変換します。別の区切り文字を使うファイルには delimiter=";"(または "\t")を渡します。
import csv
# DictReader gives each row as a dict; cells are strings
closes = []
with open("prices.csv", newline="", encoding="utf-8") as file:
for row in csv.DictReader(file):
closes.append(float(row["close"]))
print(closes) # [184.25, 185.5]
# csv.reader gives plain lists, header included
with open("prices.csv", newline="", encoding="utf-8") as file:
rows = list(csv.reader(file))
print(rows[0]) # ['date', 'symbol', 'close', 'note']
print(rows[1]) # ['2025-01-02', 'AAPL', '184.25', 'Q3, adjusted']行を書く
csv.writer(file).writerow(values) は1行を書き込み、必要なら引用符を付け、数値は自動でテキストに変換します。csv.DictWriter(file, fieldnames=[...]) は辞書を書き込み、writeheader() は先に列名を書きます。ファイルは "w" と newline="" で開きます。newline="" がないと、Windows では行の間に空行が入ることがあります。
import csv
# DictWriter: header first, then one dict per row
trades = [{"symbol": "AAPL", "quantity": 200}, {"symbol": "MSFT", "quantity": 50}]
with open("trades.csv", "w", newline="", encoding="utf-8") as file:
writer = csv.DictWriter(file, fieldnames=["symbol", "quantity"])
writer.writeheader()
writer.writerows(trades)
with open("trades.csv", encoding="utf-8") as file:
print(file.read().splitlines()) # ['symbol,quantity', 'AAPL,200', 'MSFT,50']import csv
# Cells are text until you convert them
with open("prices.csv", newline="", encoding="utf-8") as file:
row = next(csv.DictReader(file))
print(repr(row["close"]), row["close"] * 2) # '184.25' 184.25184.25
print(float(row["close"]) * 2) # 368.5
# Another separator: semicolons
with open("euro.csv", "w", newline="", encoding="utf-8") as file:
csv.writer(file, delimiter=";").writerow(["AAPL", "184,25"])
with open("euro.csv", newline="", encoding="utf-8") as file:
print(next(csv.reader(file, delimiter=";"))) # ['AAPL', '184,25']読み込むとすべて文字列になるCSV ファイルには型がありません。
184.25、200、AAPL は変換するまでただの文字です。これを忘れると、エラーではなく "184.25" * 200(文字列が200回繰り返される)になります。各列は読み込む場所で一度だけ変換し、位置を決めつけず、ヘッダーの名前で指定しましょう。newline=""で開く。CSV の行を手作業で分割・結合しないcsv.DictReaderは行を辞書として読む。各セルは文字列csv.writer/csv.DictWriter:行を書き、引用符も自動で付ける
次は JSON データです。フラットな表に収まらない入れ子のレコードを扱います。
ラボ:採点される内容
read_closesで終値をシンボルごとにまとめる25点write_tradesで約定を CSV ファイルに保存する25点total_by_symbolでシンボルごとの約定金額を合計する25点filter_rowsで特定シンボルの行を新しいファイルへコピーする25点