Polars Excelファイルの読み込みとシート名の取得 – Python

Programming
スポンサーリンク

はじめに

Pythonでのテーブルデータ処理のライブラリとして、最近、処理が高速等の理由からPolarsが流行っているような印象があります。勉強のためにもPandasで行っていた処理をPolarsに移行しようと思いました。

Excel読み込みのオプション(sheet_name, sheet_id, skip_rowの指定)と、Excelのシート名の取得がすぐにわからなかったので、下記で試しながら比較していきます。

PolarsでExcel読み込みとシート名の取得

リファレンス、参考にさせていただいたサイト

用意したExcelファイル

まず、用意したExcelファイルを下記に示します。

シートは3つ含まれています。Sheet1は、邪魔な行が1行あり、その後にcol1, col2というHeader行がある想定です。

  • Sheet1
  • Sheet2
  • Sheet3
test.xlsx

1) Excel読み込み(sheet_nameとsheet_id)

1-1) 引数にパスだけ指定した場合

コード

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 1-1) Excelファイルの読み込み
    excel_data = pl.read_excel(
        source=path,
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

if __name__ == "__main__":
    main()

出力

<class 'polars.dataframe.frame.DataFrame'>
shape: (7, 2)
┌────────┬─────────┐
│ header ┆ header2 │
│ ---    ┆ ---     │
│ str    ┆ str     │
╞════════╪═════════╡
│ col1   ┆ col2    │
│ 0      ┆ 3       │
│ 1      ┆ 1       │
│ 1      ┆ 2       │
│ 2      ┆ 4       │
│ 3      ┆ 5       │
│ 4      ┆ 6       │
└────────┴─────────┘

デフォルトでは、1つ目のシート(Sheet1)が読み込まれるようです。返ってくる型は、DataFrameです。

1-2) sheet_id 引数

コード

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 1-2) sheet_id 引数
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

if __name__ == "__main__":
    main()

出力

<class 'polars.dataframe.frame.DataFrame'>
shape: (7, 2)
┌────────┬─────────┐
│ header ┆ header2 │
│ ---    ┆ ---     │
│ str    ┆ str     │
╞════════╪═════════╡
│ col1   ┆ col2    │
│ 0      ┆ 3       │
│ 1      ┆ 1       │
│ 1      ┆ 2       │
│ 2      ┆ 4       │
│ 3      ┆ 5       │
│ 4      ┆ 6       │
└────────┴─────────┘

sheet_id引数を1に指定しました。この場合、返ってくるのはSheet1のDataFrameです。1-1)と同じですね。

1-3) sheet_name 引数

コード

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 1-3) sheet_name 引数
    excel_data = pl.read_excel(
        source=path,
        sheet_name="Sheet1",
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

if __name__ == "__main__":
    main()

出力

<class 'polars.dataframe.frame.DataFrame'>
shape: (7, 2)
┌────────┬─────────┐
│ header ┆ header2 │
│ ---    ┆ ---     │
│ str    ┆ str     │
╞════════╪═════════╡
│ col1   ┆ col2    │
│ 0      ┆ 3       │
│ 1      ┆ 1       │
│ 1      ┆ 2       │
│ 2      ┆ 4       │
│ 3      ┆ 5       │
│ 4      ┆ 6       │
└────────┴─────────┘

sheet_name引数を”Sheet1″に指定しました。この場合も返ってくるのはSheet1のDataFrameです。1-1),1-2)と同じです。

2) Excelファイルのシート名の取得

シートを指定して、Excelファイルを読み込む方法はわかりました。では、例えばExcelファイルを読み込んで、シート名をコンソールに出力し、ユーザーに選んでもらう場合など、プログラム内部でシート名を扱いたい場合は、シート名を取得する必要があります。どうすればよいでしょうか。

調べてもすぐにわからなかったので、こちらにまとめておきます。

コード

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 2) シート名の取得
    excel_data = pl.read_excel(path, sheet_id=0)
    print(type(excel_data))
    # -> <class 'dict'>
    print(excel_data)
    # -> 出力参照
    print(excel_data.keys())
    # -> dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])

if __name__ == "__main__":
    main()

出力(Sheetごとのデータの中身は意味がないので、無視してください)

<class 'dict'>
{'Sheet1': shape: (7, 2)
┌────────┬─────────┐
│ header ┆ header2 │
│ ---    ┆ ---     │
│ str    ┆ str     │
╞════════╪═════════╡
│ col1   ┆ col2    │
│ 0      ┆ 3       │
│ 1      ┆ 1       │
│ 1      ┆ 2       │
│ 2      ┆ 4       │
│ 3      ┆ 5       │
│ 4      ┆ 6       │
└────────┴─────────┘, 'Sheet2': shape: (2, 2)
┌──────┬───────────────┐
│ bbb  ┆ _duplicated_0 │
│ ---  ┆ ---           │
│ i64  ┆ i64           │
╞══════╪═══════════════╡
│ 44   ┆ null          │
│ null ┆ 555           │
└──────┴───────────────┘, 'Sheet3': shape: (1, 2)
┌───────┬───────────────┐
│ ccccc ┆ _duplicated_2 │
│ ---   ┆ ---           │
│ str   ┆ i64           │
╞═══════╪═══════════════╡
│ null  ┆ 888           │
└───────┴───────────────┘}
dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])

sheet_id=0として読み込むと、全てのSheetの情報が入ったdict型で返ってくるようです。
このdictのkeyを取得することにより、シート名を取得できます。

3) Excel読み込み(skip_row)

3-1) “skip_rows”: 0

コード

下記のコードでは、Sheet1を読み込み、行方向の読み込みスキップなしとしています。
Polarsでは、read_options={"skip_rows": 0}, として行スキップを指定するようです。

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 3-1) skip_row
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
        read_options={"skip_rows": 0},
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

if __name__ == "__main__":
    main()

出力

<class 'polars.dataframe.frame.DataFrame'>
shape: (7, 2)
┌────────┬─────────┐
│ header ┆ header2 │
│ ---    ┆ ---     │
│ str    ┆ str     │
╞════════╪═════════╡
│ col1   ┆ col2    │
│ 0      ┆ 3       │
│ 1      ┆ 1       │
│ 1      ┆ 2       │
│ 2      ┆ 4       │
│ 3      ┆ 5       │
│ 4      ┆ 6       │
└────────┴─────────┘

出力は、デフォルト時と同じになります。この場合、邪魔な行もDataFrameに読み込まれてしまっています。

3-2) “skip_rows”: 1

コード

下記のコードでは、Sheet1を読み込み、最初の行の読み込みをスキップする read_options={"skip_rows": 1}, としています。

def get_args() -> argparse.Namespace:
    # 略 コード全体を参照

def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 3-2) skip_row
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
        read_options={"skip_rows": 1},
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

if __name__ == "__main__":
    main()

出力

<class 'polars.dataframe.frame.DataFrame'>
shape: (6, 2)
┌──────┬──────┐
│ col1 ┆ col2 │
│ ---  ┆ ---  │
│ i64  ┆ i64  │
╞══════╪══════╡
│ 0    ┆ 3    │
│ 1    ┆ 1    │
│ 1    ┆ 2    │
│ 2    ┆ 4    │
│ 3    ┆ 5    │
│ 4    ┆ 6    │
└──────┴──────┘

期待通りの出力となりました。
邪魔な1行目はスキップされ、DataFrameのデータの部分には数値データのみとなっています。

コード全体

argparseでコマンドラインからExcelファイルパスを取得し、ファイルの読み込みを行っています。

Usage

python trial_polars.py -f test.xlsx

コード全体

import argparse

import polars as pl


# --- !!! Excel処理とは無関係 コマンドライン引数の処理
def get_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(description="Read Excel file")
    parser.add_argument(
        "-f",
        "--excel_file",
        type=str,
        required=True,
        help="Path to the Excel file",
    )
    args = parser.parse_args()

    return args


def main() -> None:
    args = get_args()
    path = args.excel_file

    # --- 1-1) Excelファイルの読み込み
    excel_data = pl.read_excel(
        source=path,
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

    # --- 1-2) sheet_id 引数
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

    # --- 1-3) sheet_name 引数
    excel_data = pl.read_excel(
        source=path,
        sheet_name="Sheet1",
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

    # --- 2) シート名の取得
    excel_data = pl.read_excel(path, sheet_id=0)
    print(type(excel_data))
    # -> <class 'dict'>
    print(excel_data)
    # -> 出力参照
    print(excel_data.keys())
    # -> dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])

    # --- 3-1) skip_row
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
        read_options={"skip_rows": 0},
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照

    # --- 3-2) skip_row
    excel_data = pl.read_excel(
        source=path,
        sheet_id=1,
        read_options={"skip_rows": 1},
    )
    print(type(excel_data))
    # -> <class 'polars.dataframe.frame.DataFrame'>
    print(excel_data)
    # -> 出力参照


if __name__ == "__main__":
    main()

おわりに

リファレンスをちゃんと読めば書いてあったのかと思いますが、Web検索やChatGPTの返答でもシート名の取得等はすぐに分からなかったので、メモとして残しました。

コメント

タイトルとURLをコピーしました