Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

Polarsの使い方(XBP用)

Posted at

Polars基本メソッド説明集

はじめに:Polarsの特徴とメソッドチェーン

Polarsの最大の特徴は、メソッドチェーンで処理を繋げられることです。データの読み込みから変換、フィルタリング、集計まで、一連の処理を直感的に記述できます。

基本的なメソッドチェーンの例

import polars as pl
df_sales = pl.read_csv('sales.csv')  # 1. 読み込み

# 一連の処理を実行
(df_sales
    .filter(pl.col('price') > 0)                 # 4. 抽出(3.判定系使用)
    .with_columns(                               # 8. 追加
        # 7. 条件分岐(3.判定系使用)
        pl.when(pl.col('price') > 1000).then('高額').otherwise('通常')
          .alias('price_category')               # 9. その他(列名変更)
    )
    .group_by('price_category')                  # 10. グループ化
    .agg(pl.col('price').mean())                 # 10. グループ化(6.計算系)
    .sort('price', descending=True)              # 9. その他(並び替え)
    .head(10)                                    # 2. 最終確認
)
  • コツ1:括弧でメソッド全体を囲むことで複数行に分けて書く
  • コツ2:各メソッドの前に改行を入れる
  • コツ3:インデントを揃えて可読性を高める
  • コツ4:適宜コメントアウトしながら途中経過を確認する

1. データ読み込み

pl.read_csv()

CSVファイルを読み込んでDataFrameを作成します。ここからメソッドチェーンが始まります。

df = pl.read_csv('data.csv', schema_overrides=dtypes, encoding='utf-8-sig')

2. データ確認(データの把握・最終確認)

head()

データフレームの先頭から指定した行数を表示します。

df.head(3)  # 先頭3行を表示

# 使用例
(df_sales
    .filter(pl.col('price') > 100)
    .head(5)
)

tail()

データフレームの末尾から指定した行数を表示します。

df.tail(3)  # 末尾3行を表示

# 使用例
(df_orders
    .sort('order_date')
    .tail(10)  # 日付順に並べて最新10件
)

shape

データフレームの形状(行数、列数)を取得します。

df.shape  # (行数, 列数)のタプルを返す

# 使用例(shapeはプロパティなのでチェーンの最後に使用する)
(df_status
    .filter(pl.col('status') == 'active')
    .shape  # メソッドではないので括弧も不要
)

null_count()

各列の欠損値の数を確認します。

df.null_count()

# 使用例
(df_products
    .select('price', 'quantity')
    .null_count()
)

unique()

指定した列のユニークな値を取得します。

df.select(pl.col('color')).unique()

# 使用例
(df_inventory
    .filter(pl.col('price') > 100)
    .select('category')
    .unique()
)

sample()

データからランダムサンプリングを行います。

df.sample(n=10)           # 10件をランダムに抽出
df.sample(fraction=0.05)  # 5%をランダムに抽出

# 使用例
(df_electronics
    .filter(pl.col('category') == 'Electronics')
    .sample(n=100)
    .sort('price')
)

3. 判定系(条件を作る)

数値比較

基本的な数値の比較演算子です。

pl.col('price') > 1000    # 1000より大きいという条件
pl.col('price') <= 500    # 500以下という条件
pl.col('price') == 1000   # 1000であるという条件
pl.col('price') != 0      # 0ではないという条件

# 使用例
(df_items
    .filter(pl.col('price') >= 500)
)

str.contains()

文字列に特定の文字が含まれているかチェックします。

pl.col('city').str.contains('東京')

# 使用例
(df_location
    .filter(pl.col('city').str.contains('東京'))
    .group_by('district')
    .agg(pl.col('sales').sum())
    .sort('sales', descending=True)
)

str.starts_with()

文字列が特定の文字で始まるかチェックします。

pl.col('product_code').str.starts_with('A')

# 使用例
(df_products
    .filter(pl.col('product_code').str.starts_with('A'))
    .select('product_code', 'product_name', 'price')
    .sort('product_code')
)

is_between()

値が指定した範囲内にあるかチェックします。

pl.col('score').is_between(80, 100)

# 使用例
(df_scores
    .filter(pl.col('score').is_between(80, 100))
)

is_null(), is_not_null()

欠損値の有無をチェックします。

pl.col('email').is_null()
pl.col('email').is_not_null()

# 使用例
(df_customers
    .filter(pl.col('email').is_not_null())
)

& (AND演算子)

複数の条件を結合してチェックします。

(pl.col('price') >= 100) & (pl.col('stock') > 0)

# 使用例
(df_active
    .filter(
        (pl.col('price') > 0) & 
        (pl.col('stock') > 0) & 
        (~pl.col('status').str.contains('廃止'))
    )
    .sort('price')
)

| (OR演算子)

複数の条件のいずれかが満たされるかをチェックします。

シフトを押しながらキーボードの右上にある該当するキーをクリックすると入力できます。

(pl.col('category') == 'Electronics') | (pl.col('category') == 'Books')

# 使用例
(df_multiple_categories
    .filter(
        (pl.col('category') == 'Electronics') | 
        (pl.col('category') == 'Books') | 
        (pl.col('price') > 1000)
    )
    .sort('price', descending=True)
)

~ (NOT演算子)

条件を否定します。

~pl.col('status').str.contains('無効')  # "無効"が含まれていないかどうかをチェックする

# 使用例
(df_filtered
    .filter(~pl.col('product_code').str.starts_with('A'))  # Aから始まらない行を抽出
)

4. 抽出系(行・列を絞る)

filter()

条件に基づいて行を抽出します。

df.filter(pl.col('price') >= 500)

# 使用例
(df_expensive
    .filter(pl.col('price') >= 1000)
    .filter(pl.col('stock') > 0)
    .select('product_name', 'price')
    .sort('price', descending=True)
)

select()

指定した列を抽出します。

df.select('price')          # 1列を選択
df.select('name','age')     # 複数列を選択

# 使用例
(df_active
    .filter(pl.col('status') == 'active')
    .select('product_name', 'price', 'category')
    .sort('price')
)

drop()

指定した列を削除します。

df.drop('unwanted_column')           # 1列を削除
df.drop('col1', 'col2', 'col3')    # 複数列を削除

# 使用例
(df_clean
    .drop('temp_id', 'internal_notes', 'debug_info')
    .filter(pl.col('is_valid') == True)
)

5. 変換系(データの型を変える)

cast()(さまざまな型の変換が可能)

データ型を変換します。本講義では「数値型→文字列型」に利用します。

pl.col('order_id').cast(str)  # 数値型から文字列型に変換

# 使用例
(df_orders
    .with_columns(
        pl.col('order_date').cast(str)
    )
    .filter(pl.col('order_date').str.starts_with('2024'))
)

str.strptime()(文字列→日付の型変換)

文字列型を日付型に変換します。

pl.col('order_date').str.strptime(pl.Date, "%Y%m%d")  # Yは年、mは月、dは日

# 使用例
(df_orders
    .with_columns(
        pl.col('order_date').str.strptime(pl.Date, "%Y%m%d")
    )
    .filter(pl.col('order_date') >= pl.date(2024, 1, 1))
    .sort('order_date')
)

dt.strftime()(日付→文字列の型変換)

日付型を文字列型に変換します。

pl.col('order_date').dt.strftime('%Y%m%d')  # Yは年、mは月、dは日

# 使用例
(df_monthly
    .with_columns(
        pl.col('order_date').dt.strftime('%Y%m%s').alias('date')
    )
    .group_by('date')
    .agg(pl.col('sales').sum())
)

dt.day()

日付から「日」の部分を数値で取得します。

pl.col('order_date').dt.day()  # 日付から日を抽出(1-31)

# 使用例
(df_orders
    .with_columns(
        pl.col('order_date').dt.day().alias('day')
    )
    .filter(pl.col('day') <= 15)  # 月の前半のデータのみ抽出
)

dt.month()

日付から「月」の部分を数値で取得します。

pl.col('order_date').dt.month()  # 日付から月を抽出(1-12)

# 使用例
(df_orders
    .with_columns(
        pl.col('order_date').dt.month().alias('month')
    )
    .filter(pl.col('month').is_in([6, 7, 8]))  # 夏季(6-8月)のデータのみ抽出
)

dt.weekday()

日付から「曜日」を数値で取得します。

pl.col('order_date').dt.weekday()  # 曜日を数値で取得(月曜=1, 日曜=7)

# 使用例
(df_orders
    .with_columns(
        pl.col('order_date').dt.weekday().alias('weekday')
    )
    .filter(pl.col('weekday').is_in([6, 7]))  # 土日のデータのみ抽出
)

6. 計算系(数値を計算する)

四則演算

基本的な算術演算子です。

pl.col('price') + pl.col('tax')           # 加算
pl.col('revenue') - pl.col('cost')        # 減算
pl.col('price') * pl.col('quantity')      # 乗算
pl.col('profit') / pl.col('revenue')      # 除算
pl.col('score') // 10                     # 整数除算

# 使用例
(df_profits
    .with_columns(
        (pl.col('revenue') - pl.col('cost')).alias('profit'),
        ((pl.col('revenue') - pl.col('cost')) / pl.col('revenue')).alias('profit_rate')
    )
    .filter(pl.col('profit') > 0)
    .sort('profit_rate', descending=True)
)

集計・数学関数

pl.len()                    # 行数カウント
pl.col('price').sum()       # 合計値
pl.col('price').mean()      # 平均値
pl.col('order_date').max()  # 最大値
pl.col('order_date').min()  # 最小値
pl.col('price').std()       # 標準偏差
pl.col('order_date').n_unique()  # ユニーク数
pl.col('category').first()  # 最初の値
pl.col('target').abs()      # 絶対値
(pl.col('price') * 1.08).floor()  # 小数点切り捨て

# 使用例
(df_analytics
    .filter(pl.col('status') == 'completed')
    .group_by('region')
    .agg(
        pl.col('sales').sum().alias('total_sales'),
        pl.col('sales').mean().alias('avg_sales'),
        pl.col('customer_id').n_unique().alias('unique_customers'),
        pl.len().alias('transaction_count')
    )
    .sort('total_sales', descending=True)
)

7. 条件分岐系(場合分けして値を決める)

pl.when(判定系).then().otherwise()

判定系を用いて条件分岐を行います。

# 1000より大きければ1、そうでなければ0とする場合
pl.when(pl.col('price') > 1000).then(1).otherwise(0)

# 複数の条件分岐を繋げることも可能
pl.when(pl.col('region').str.contains('関東')).then(1)
  .when(pl.col('region').str.contains('関西')).then(2)
  .otherwise(0)

# 使用例
(df_categories
    .with_columns(
        pl.when(pl.col('price') >= 1000).then('高額商品')
          .when(pl.col('price') >= 500).then('中額商品')
          .otherwise('低額商品')
          .alias('price_category')
    )
    .group_by('price_category')
    .agg(pl.len().alias('count'))
    .sort('count', descending=True)
)

8. 追加系(新しい列を作る)

with_columns()

新しい列を追加または既存の列を変更します。変換系、計算系、条件分岐系を組み合わせて使用します。

# totalという列名で追加する場合
df.with_columns(
    (pl.col('price') * pl.col('quantity')).alias('total')
)

# 使用例
(df_enhanced
    .with_columns(
        (pl.col('price') * pl.col('quantity')).alias('total_amount'),   # 計算系
        (pl.col('price') * 1.1).alias('price_with_tax'),                # 計算系
        pl.col('order_date').dt.strftime('%Y-%m').alias('order_month'), # 変換系
        pl.when(pl.col('price') > 1000).then('高額').otherwise('通常').alias('category') # 条件分岐系
    )
    .filter(pl.col('total_amount') > 1000)
    .sort('total_amount', descending=True)
)

9. その他

shift()(ずらす操作)

データを指定した行数分シフトします(ラグ機能)。

pl.col('sales').shift(1)     # 1行分うしろにずらす
pl.col('sales').shift(2)     # 2行分うしろにずらす

# 使用例
(df_timeseries
    .sort('date')
    .with_columns(
        pl.col('sales').shift(1).alias('prev_sales'),
        (pl.col('sales') - pl.col('sales').shift(1)).alias('sales_change')
    )
    .filter(pl.col('sales_change').is_not_null())
    .select('date', 'sales', 'prev_sales', 'sales_change')
)

drop_nulls(), fill_null()(欠損値処理)

欠損値を削除または指定した値で埋めます。

df.drop_nulls()  # いずれかの列に欠損値がある行を削除
pl.col('discount').fill_null(0)    # 欠損値を0にする

# 使用例
(df_cleaned
    .drop_nulls()
    .filter(pl.col('price') > 0)
    .sort('order_date')
)

alias()

列名に別名を付けます。複雑な計算の列を生成を生成した場合は別名をつけないとエラーになることも。

pl.col('order_date').alias('purchase_date')

# 使用例
(df_renamed
    .with_columns(
        (pl.col('price') * 1.1).alias('price_with_tax')
    )
    .select('product', 'price', 'price_with_tax')
)

pl.col()

列に対していろいろなメソッドを適用するための関数です。

pl.col('price')           # 列を操作対象として指定
pl.col('price').sum()     # 列に対して合計を計算

# 使用例
(df_converted
    .with_columns(
        pl.col('price').cast(pl.Float64).alias('price_float')
    )
    .select('product', 'price_float')
)

sort()

データフレームを指定した列で並び替えます。

df.sort('price')                         # 昇順
df.sort('price', descending=True)        # 降順
df.sort('category', 'price')             # 複数列で並び替え

# 使用例
(df_ranking
    .filter(pl.col('stock') > 0)
    .sort('sales_count', descending=True)
    .head(10)
    .select('product_name', 'sales_count', 'price')
)

10. グループ化系(グループごとに計算する)

group_by()

指定した列でデータをグループ化します。

df.group_by('category')                  # 単一列でグループ化
df.group_by('category', 'brand')         # 複数列でグループ化

# 使用例(group_byの後は必ずaggが必要)
(df_summary
    .filter(pl.col('price') > 0)
    .group_by('category')
    .agg(
        pl.col('price').mean().alias('avg_price'),
        pl.col('sales').sum().alias('total_sales'),
        pl.len().alias('product_count')
    )
    .sort('total_sales', descending=True)
)

agg()

グループ化後に集計を行います。計算系や判定系を組み合わせて使用します。

df.group_by('category').agg(
    pl.col('price').sum(),  # 計算系:グループ毎に合計値を抽出
    pl.col('stock').mean()  # 計算系:グループ毎に平均値を抽出
)

# 使用例
(df_report
    .with_columns(
        pl.col('order_date').dt.strftime('%Y-%m').alias('month')
    )
    .group_by('month')
    .agg(
        pl.col('revenue').sum().alias('total_revenue'),
        pl.col('order_id').n_unique().alias('order_count')
    )
    .sort('month')
)

# 高度な使用例:判定系と計算系の組み合わせ
(df_report
    .group_by('category')
    .agg(
        pl.col('price').filter(pl.col('stock') > 100).max()  # 判定系 + 計算系
    )
)

len()(集計関数として)

グループ内の行数をカウントします。

df.group_by('category').len()

11. データ結合(複数テーブルの統合)

join()

データフレーム同士を結合します。

df1.join(df2, how='inner', on='product_id')     # 内部結合
df1.join(df2, how='left', on='product_id')      # 左結合
df1.join(df2, how='full', on='product_id')      # 外部結合

# 使用例
(df_sales
    .join(df_products, on='product_id', how='left')
    .join(df_categories, on='category_id', how='left')
    .filter(pl.col('sales_amount') > 100)
    .group_by('category_name')
    .agg(pl.col('sales_amount').sum().alias('total_sales'))
    .sort('total_sales', descending=True)
)

12. データ変形

pivot()

データをピボットテーブル形式に変換します。縦長データを横長データ(クロス集計表)に変換する機能です。

pivot()の仕組み:

  • index: 行(縦軸)にしたい列を指定
  • on: 列(横軸)にしたい列を指定
  • values: 各セルに配置する値の列を指定

実行前データ

month region sales
1月 東京 100
1月 大阪 80
2月 東京 120
2月 大阪 90
3月 東京 110
3月 大阪 95
df.pivot(values='sales', index='month', on='region')  # 実行すると以下の形になる

実行後データ

month 東京 大阪
1月 100 80
2月 120 90
3月 110 95
# 使用例
(df_pivot
    .filter(pl.col('year') == 2024)
    .group_by('month', 'region')
    .agg(pl.col('sales').sum())
    .pivot(values='sales', index='month', on='region')
    .sort('month')
)

13. データ出力・可視化

to_pandas()

Polars形式からPandas形式に変換します。グラフ作成にあたって必ず最初に必要となる処理です。

df.to_pandas()  # matplotlib用に変換する

# 使用例(可視化前の準備)
(df_chart
    .group_by('month')
    .agg(pl.col('revenue').sum())
    .sort('month')
    .to_pandas()  # matplotlibで使用するためPandasに変換
)

Matplotlib(可視化)

基本設定

import matplotlib.pyplot as plt
plt.rcParams['font.family'] = ['IPAexGothic']  # 日本語フォント設定

可視化の流れ

# Polarsでデータを準備してからPndasに変換してmatplotlibで可視化
(df.group_by('category')
   .agg(pl.col('sales').sum())
   .sort('sales', descending=True)
   .to_pandas()  # matplotlib用にPandasに変換
   .plot(kind='bar', x='category', y='sales', figsize=(10, 6))
)

# 細かいグラフの調整は括弧の外で行う
plt.title('カテゴリ別売上')
plt.xlabel('カテゴリ')
plt.ylabel('売上金額')

plot()

グラフを作成します。

df.plot(kind='bar', x='category', y='sales')      # 棒グラフ(yの指定は省略可)
df.plot(kind='line', x='month', y='revenue')      # 折れ線グラフ(yの指定は省略可)
df.plot(kind='bar', stacked=True)                 # 積み上げ棒グラフ

グラフオプション

この他にもさまざまなグラフオプションが選べます。

# 棒グラフのオプション
df.plot(kind='bar', x='region', figsize=(6,4), rot=45)

# 折れ線グラフのオプション
df.plot(kind='line', marker='o', linestyle='--')

グラフの装飾

plt.title(), plt.xlabel(), plt.ylabel()

グラフのタイトルと軸ラベルを設定します。

plt.title('売上推移')
plt.xlabel('')
plt.ylabel('売上金額')

plt.subplots()

複数軸のグラフを作成することも可能です。まずはグラフエリアとプロットエリアを生成します。

legend()

凡例を設定します。

plt.legend('売上', loc='upper right')

twinx()

右側のY軸を基準とするグラフを追加します。

ax2 = ax1.twinx()

# 使用例
fig, ax1 = plt.subplots(figsize=(10,6))
ax2 = ax1.twinx()
## 途中は省略(ひとつ目のグラフのためのデータ処理)
   .to_pandas()
   .plot(kind='line', color='black', ax=ax1)  # このグラフのY軸の値は左軸が基準になる
## 途中は省略(二つ目のグラフのためのデータ処理)
   .to_pandas()
   .plot(kind='line', color='red', ax=ax2)  # このグラフのY軸の値は右軸が基準になる
0

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?