やましなぶろぐ

sqlのWindowFunction:分析関数をPandas.expandingで実装

WindowFunctionの機能が強力なのでPandasでの実装方法も試しておきたい

データサイエンス100本ノックにもそれらしき問題がないので問題を自作します

🕒 Last mod: 2021-02-13


1. SQLのWindowFunctionが強力

SQLについては必要なときには調べれば大抵の処理は実装できるだろうと舐めているところがありました。

私の若かかりし頃にはなかった分析関数がいつの間にか実装されていて、その機能がまた強力なのです。

そして、実際に試してみないと分析関数が何ができるのか、何が強力なのかが理解するのが難しいのが悩ましいところ。

実際に分析関数を多用する状況に追い込まれて、やっとその便利さに気づきました。

そして分析関数と同様の処理をPandasで実装するにはどうすれば良いのかと当然ながら思います。

この記事では分析関数に関する問題を一つ作成してSQLとPandasでの回答例を紹介します。

「データサイエンティスト協会スキル定義委員」の「データサイエンス100本ノック(構造化データ加工編)」を利用しています

2. レシート明細データフレーム(df_receipt)の売上金額(amount)を日付(sales_ymd)ごとに集計し、各日付のデータに対しその日付までの最小値の売上金額を計算せよ。

自作の問題です。

分析関数はTimeSeriesのデータに対して便利な機能を提供しています。

しっかりと理解するにはWindowRangeやWindowFrameを理解する必要があり難しいです。私自身も色々試して理解を深めていかなければなりません。

この問題は分析関数の一つの利用例になります。

3. SQLでの回答例

分析関数を使用します。このSQL文ではWindow Frameを良く理解する必要があります。

処理結果が直ぐに分からない場合はWindow Frameなどで検索してみてください。

answer.sql
with amount_by_ymd as(
  select
    sales_ymd,
    sum(amount) amount
  from
    receipt
  group by
    sales_ymd
)
select
  sales_ymd,
  amount,
  min(amount)
  over (order by sales_ymd)
  min_amount_ever
from
  amount_by_ymd
limit 10
;
output
 sales_ymd | amount | min_amount_ever
-----------+--------+-----------------
  20170101 |  33723 |           33723
  20170102 |  24165 |           24165
  20170103 |  27503 |           24165
  20170104 |  36165 |           24165
  20170105 |  37830 |           24165
  20170106 |  32387 |           24165
  20170107 |  23415 |           23415
  20170108 |  24737 |           23415
  20170109 |  26718 |           23415
  20170110 |  20143 |           20143
(10 rows)

4. pandasの回答例

expanding()を使用します。

answer.py
answer = (
    df_receipt
    .groupby('sales_ymd')
    .agg(
        amount=('amount', 'sum')
    )
    .assign(
        min_amount_ever=lambda x:
        x.amount.expanding().min()
    )
)
answer.head(10)
output
           amount  min_amount_ever
sales_ymd
20170101    33723          33723.0
20170102    24165          24165.0
20170103    27503          24165.0
20170104    36165          24165.0
20170105    37830          24165.0
20170106    32387          24165.0
20170107    23415          23415.0
20170108    24737          23415.0
20170109    26718          23415.0
20170110    20143          20143.0

5. まとめ

SQLは分析のためのデータ加工ツールとしては機能が不足していると舐めていましたが分析関数の強力さを思い知らされました。

分析関数を使いこなすのは難しく、まだまだ色々な応用例が数多くあります。

これからも修練を積み重ねたいと思います。