@shiracamus(しらかみゅ)さんコメントありがとうございます。
丸目の使用対応のため、以下の部分を修正(デフォルトが銀行まとめ)
<rounded_value = round(float(value), 1)
>from decimal import Decimal, ROUND_HALF_EVEN
>rounded_value = value.quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)
さんソース
https://note.nkmk.me/python-round-decimal-quantize/
https://docs.python.org/ja/3/library/decimal.html#decimal.Decimal.quantize
import csv
from decimal import Decimal, ROUND_HALF_EVEN
input_file = "input.csv" # 入力CSVファイル
output_file = "output.csv" # 出力CSVファイル
with open(input_file, newline="", encoding="utf-8") as f:
reader = csv.reader(f)
header = next(reader) # ヘッダーを読み込む
rows = []
for row in reader:
new_row = []
for value in row:
try:
# 数値として扱える場合は四捨五入
rounded_value = value.quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)
new_row.append(str(rounded_value)) # 文字列に戻してリストに追加
except ValueError:
# 数値でなければそのまま追加
new_row.append(value)
except AttributeError:
# 数値でなければそのまま追加
new_row.append(value)
rows.append(new_row)
with open(output_file, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(header) # ヘッダーを書き込む
writer.writerows(rows) # データを書き込む
print(f"変換完了!出力ファイル: {output_file}")
指定した列を除外
import csv
from decimal import Decimal, ROUND_HALF_EVEN
def round_numeric_columns(input_file: str, output_file: str, exclude_columns: list) -> None:
"""
CSVファイル内の数値列をすべて小数点第一位で四捨五入し、指定された列はそのまま保持する。
Args:
input_file (str): 入力CSVファイルのパス
output_file (str): 出力CSVファイルのパス
exclude_columns (list): 四捨五入しない列名のリスト
"""
with open(input_file, newline="", encoding="utf-8-sig") as f:
reader = csv.reader(f)
header = next(reader) # ヘッダーを取得
exclude_indices = [header.index(col) for col in exclude_columns if col in header] # 除外する列のインデックス
rows = []
for row in reader:
new_row = []
for i, value in enumerate(row):
if i in exclude_indices:
new_row.append(value) # 除外対象の列はそのまま
else:
try:
rounded_value = value.quantize(Decimal('0.1'), rounding=ROUND_HALF_EVEN)
new_row.append(str(rounded_value)) # 文字列として追加
except ValueError:
new_row.append(value) # 数値変換できなければそのまま
except AttributeError:
new_row.append(value) # 数値変換できなければそのまま
rows.append(new_row)
# 新しいCSVを保存
with open(output_file, "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(header) # ヘッダーを書き込む
writer.writerows(rows) # データを書き込む
print(f"変換完了!出力ファイル: {output_file}")
# 使用例
round_numeric_columns("input.csv", "output.csv", ["名前", "年齢"])
>exclude_indices = [header.index(col) for col in exclude_columns if col in header]
上記のコードは1列目を指定するとインデックスが取得できなかった
→BOM付きutf-8だった
open関数のencodingを"utf-8-sig"に変更、これでBOMを読み込んだ時に自動除去されるようになった
>writer = csv.writer(f)
引数に quoting=csv.QUOTE_ALLで全項目にダブルクォーテーションを付けて出力
writer = csv.writer(f, quoting=csv.QUOTE_ALL)