0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CSV:数値と文字列のあるCSVの数値を四捨五入する(Python)

Last updated at Posted at 2025-03-19

@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)

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?