intellista

engineer's notes about application development, data analysis, and so on

PythonでPandasを使ってCSVをサクッと整形する方法とは?

こんにちは!

Pythonを使ったデータ分析やアプリケーション開発において、CSVファイルを扱う機会はよくあります。
CSVの読み書き、整形をPythonで行うなら、Pandasを使うのがとても簡単です。
コード量も少なく可読性もいいので、メンテナンス性も確保できます。

今回は、PythonでPandasを使ってCSVをサクッと整形する方法をご紹介します。

基本構造

PythonでPandasを使ってCSVをサクッと整形する処理の基本構造は、次のとおりです。

import pandas as pd

def main():

    df = pd.read_csv(  # 読み込み
        "./input.csv",  # 入力ファイル
        dtype=str  # 値が化けないように
    ) 

    df = edit(df)  # データ加工

    df.to_csv(  # 書き出し
        "./output.csv",  # 出力ファイル
        index=False  # read_csv()で付加されたindexを除去
    )

def edit(df):  # データ加工
    # df を加工する処理を記述する
    return df

if __name__ == "__main__":
    main()


Pandasは本当に便利ですね。

なお、Pandasによって「値が変わってしまう事象」が発生しないように、dtype=strをしていして、すべての値を文字列として読み込みます。

dtypeを指定しないと、Pandasがうまいこと型を推測しようとしてくれます。(型推測、とよばれます。)
しかし、数値が一律floatになって小数点が付いてしまうといった「値が変わってしまう事象」が発生します。

「値が変わってしまう事象」が発生すると、何が問題なのでしょうか?

例えば、DBから取得したCSVを加工してから、同じテーブルに入れようとすると、エラーが発生する可能性があります。
整数型のカラム値「1」について、CSV出力した時点では「1」のままですが、Pandasによりfloatで読み込まれて「1.0」に変換され、そのままCSVに「1.0」で出力されたとき、それをDBにINSERTしようとすると「1.0」は整数ではないのでDBへのINSERTでエラーとなります。

なので、Pandasで読み込む前のCSVと書き出したあとのCSVの型を同じにする工夫が必要となります。
この工夫として、文字列として扱うのが手っ取り早いです。

いくつかの加工処理の例

加工処理について、いくつかの例を挙げます。

最終列を除去する

最終列を除去するには、次のようにします。

import pandas as pd

def main():
    df = pd.read_csv(  # 読み込み
        "./input.csv",  # 入力ファイル
        dtype=str  # 値が化けないように
    ) 

    df = edit(df)  # データ加工

    df.to_csv(  # 書き出し
        "./output.csv",  # 出力ファイル
        index=False  # read_csv()で付加されたindexを除去
    )

def edit(df):  # データ加工
    df = df.iloc[:, :-1]  # 最終列を除去
    return df

if __name__ == "__main__":
    main()

ヘッダを除去する

ヘッダを除去するには、次のようにします。

import pandas as pd

def main():
    df = pd.read_csv(  # 読み込み
        "./input.csv",  # 入力ファイル
        dtype=str  # 値が化けないように
    ) 

    df = edit(df)  # データ加工

    df.to_csv(  # 書き出し
        "./output.csv",  # 出力ファイル
        index=False,  # read_csv()で付加されたindexを除去
        header=False  # ヘッダを出力しない
    )

def edit(df):  # データ加工
    # df を加工する処理を記述する
    return df

if __name__ == "__main__":
    main()

文字コードを変換する

文字コードを変換するには、次のようにします。

import pandas as pd

def main():
    df = pd.read_csv(  # 読み込み
        "./input.csv",  # 入力ファイル
        dtype=str,  # 値が化けないように
        encoding = "shift-jis"  # SJISで読み込み。CP932相当。
    ) 

    df = edit(df)  # データ加工

    df.to_csv(  # 書き出し
        "./output.csv",  # 出力ファイル
        index=False,  # read_csv()で付加されたindexを除去
        encoding = "utf-8"  # UTF-8で書き出し。
    )

def edit(df):  # データ加工
    # df を加工する処理を記述する
    return df

if __name__ == "__main__":
    main()

なお、

  • BOMなし: encoding = "utf-8"
  • BOMつき: encoding = "utf-8_sig"

となります。

カラムの前後の空白を除去する

カラムの前後の空白を除去するには、次のようにします。

import pandas as pd

def main():
    df = pd.read_csv(  # 読み込み
        "./input.csv",  # 入力ファイル
        dtype=str  # 値が化けないように
    ) 

    df = edit(df)  # データ加工

    df.to_csv(  # 書き出し
        "./output.csv",  # 出力ファイル
        index=False  # read_csv()で付加されたindexを除去
    )

def edit(df):  # データ加工
    # df を加工する処理を記述する
    df.iloc[:, 0] = df.iloc[:, 0].str.strip()
    return df

if __name__ == "__main__":
    main()

補足

巨大なCSVファイルの場合

巨大なファイルの場合はPandasのread_csv()のchunksizeオプションを使えば読み込める可能性があります。
本記事では本論でないため、申し訳ありませんが割愛します。

文字コードだけなら標準関数でOK

単に文字コードを変換するだけなら、Python組み込みの標準関数open()、write()で十分です。
例えば、Shift_JISからUTF-8に変換するには、下記のようにします。

with open('./input.csv', encoding="cp932") as fin:
    with open('./output.csv', 'w', encoding="utf8") as fout:
        fout.write(fin.read())

ただし、こちらも巨大なファイルの場合は、一度に読み込むとメモリエラーとなる可能性があります。
これを防ぐため、例えば、BufferedReader、BufferedWriterなどのioパッケージのストリームを使って少しずつ読み込むのもいいと思います。

なお、encoding="cp932"のところが encoding="shift jis"でないのは、cp932のほうがカバーできる文字コードが多いためです。
encoding="cp932"にしておくのが無難です。

まとめ

今回は、PythonでPandasを使ってCSVをサクッと整形する方法をご紹介しました。
これで、Python(Pandas)を使ってCSVをの読み書きや整形を簡単に行えるようになるはずです!

なお、Pandasを含め、Pythonには様々なコツが必要なシーンが多々あります。
Python、Pandas、データ分析、に関するコツなどを次の記事にまとめてありますので、是非読んでみてください!
intellista.hatenablog.com