{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"kernelVersion","sourceId":299761547,"isSourceIdPinned":false}],"dockerImageVersionId":31286,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Init","metadata":{}},{"cell_type":"code","source":"import polars as pl # polars\nimport pandas as pd # pandas","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:21:12.947480Z","iopub.execute_input":"2026-02-24T23:21:12.947801Z","iopub.status.idle":"2026-02-24T23:21:15.081950Z","shell.execute_reply.started":"2026-02-24T23:21:12.947764Z","shell.execute_reply":"2026-02-24T23:21:15.081074Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 基礎編","metadata":{}},{"cell_type":"markdown","source":"## データ読み込み","metadata":{}},{"cell_type":"code","source":"from pathlib import Path\n\n# データディレクトリのパスを指定\n# Pathクラスでディレクトリを指定することで`/`でパスを連結できるなど取り回しが良くなる\nDATA_DIR = Path(\"/kaggle/input/notebooks/ekichi/psp-train-data\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:21:15.084167Z","iopub.execute_input":"2026-02-24T23:21:15.085143Z","iopub.status.idle":"2026-02-24T23:21:15.090808Z","shell.execute_reply.started":"2026-02-24T23:21:15.085059Z","shell.execute_reply":"2026-02-24T23:21:15.089549Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\n# Kaggle環境ではメモリ制限(OOM)回避のため、オリジナルデータから事前準備したparquetファイルをファイルを読み込む\npl_df = pl.read_parquet(DATA_DIR / \"train.parquet\")  # polars","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:21:15.092194Z","iopub.execute_input":"2026-02-24T23:21:15.092551Z","iopub.status.idle":"2026-02-24T23:21:21.484060Z","shell.execute_reply.started":"2026-02-24T23:21:15.092517Z","shell.execute_reply":"2026-02-24T23:21:21.483097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%time\n# Kaggle環境ではメモリ制限(OOM)回避のため、オリジナルデータから事前準備したparquetファイルをファイルを読み込む\npd_df = pd.read_parquet(DATA_DIR / \"train.parquet\")  # pandas","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:21:21.485466Z","iopub.execute_input":"2026-02-24T23:21:21.485873Z","iopub.status.idle":"2026-02-24T23:21:36.937272Z","shell.execute_reply.started":"2026-02-24T23:21:21.485847Z","shell.execute_reply":"2026-02-24T23:21:36.935281Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 集計","metadata":{}},{"cell_type":"code","source":"# polars\ndisplay(pl_df.group_by(\"session_id\").agg(pl.col(\"index\").count().alias(\"count\")).sort(\"count\").head())\n\n# pandas\ndisplay(pd_df.groupby(\"session_id\").agg(count=(\"index\", \"count\")).sort_values(\"count\").reset_index().head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:09.827310Z","iopub.execute_input":"2026-02-24T23:28:09.828303Z","iopub.status.idle":"2026-02-24T23:28:11.408046Z","shell.execute_reply.started":"2026-02-24T23:28:09.828271Z","shell.execute_reply":"2026-02-24T23:28:11.407294Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# polars\ndisplay(\n    pl_df.group_by(\"session_id\", maintain_order=True)\n    .agg(\n        pl.col(\"index\").count().alias(\"index_count\"),\n        pl.col(\"elapsed_time\").sum().alias(\"elapsed_time_sum\"),\n    )\n    .sort(\"index_count\")\n    .head()\n)\n\n# pandas\ndisplay(\n    pd_df.groupby(\"session_id\")\n    .agg(index_count=(\"index\", \"count\"), elasped_time_sum=(\"elapsed_time\", \"sum\"))\n    .sort_values(\"index_count\")\n    .reset_index()\n    .head()\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:11.409501Z","iopub.execute_input":"2026-02-24T23:28:11.409842Z","iopub.status.idle":"2026-02-24T23:28:13.060076Z","shell.execute_reply.started":"2026-02-24T23:28:11.409817Z","shell.execute_reply":"2026-02-24T23:28:13.059371Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# 応用編","metadata":{}},{"cell_type":"markdown","source":"## リスト形式での指定","metadata":{}},{"cell_type":"code","source":"display(\n    pl_df.group_by(\"session_id\")\n    .agg(\n        [\n            pl.col(\"index\").count().alias(\"index_count\"),\n            pl.col(\"elapsed_time\").sum().alias(\"elapsed_time_sum\"),\n        ]\n    )\n    .sort(\"index_count\")\n    .head()\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:13.061248Z","iopub.execute_input":"2026-02-24T23:28:13.061572Z","iopub.status.idle":"2026-02-24T23:28:14.032950Z","shell.execute_reply.started":"2026-02-24T23:28:13.061548Z","shell.execute_reply":"2026-02-24T23:28:14.032262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"display(\n    pl_df.group_by(\"session_id\", maintain_order=True)\n    .agg(\n        [\n            pl.col(\"index\").count().alias(\"index_count\"),\n            *[pl.col(c).sum().alias(f\"{c}_sum\") for c in [\"elapsed_time\", \"index\", \"fullscreen\", \"hq\", \"music\"]],\n        ]\n    )\n    .sort(\"index_count\")\n    .head()\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:14.033843Z","iopub.execute_input":"2026-02-24T23:28:14.034067Z","iopub.status.idle":"2026-02-24T23:28:15.130075Z","shell.execute_reply.started":"2026-02-24T23:28:14.034046Z","shell.execute_reply":"2026-02-24T23:28:15.129064Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"display(\n    pl_df.group_by(\"session_id\", maintain_order=True)\n    .agg(\n        [\n            pl.col(\"index\").count().alias(\"index_count\"),\n            pl.col(\"elapsed_time\").sum().alias(\"elapsed_time_sum\"),\n            pl.col(\"index\").sum().alias(\"index_sum\"),\n            pl.col(\"fullscreen\").sum().alias(\"fullscreen_sum\"),\n            pl.col(\"hq\").sum().alias(\"hq_sum\"),\n            pl.col(\"music\").sum().alias(\"music_sum\"),\n        ]\n    )\n    .sort(\"index_count\")\n    .head()\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:15.131959Z","iopub.execute_input":"2026-02-24T23:28:15.132318Z","iopub.status.idle":"2026-02-24T23:28:16.236298Z","shell.execute_reply.started":"2026-02-24T23:28:15.132293Z","shell.execute_reply":"2026-02-24T23:28:16.235562Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 集約したい変数リスト\nnums = [\"elapsed_time\", \"index\", \"fullscreen\", \"hq\", \"music\"]\n# aggに渡す引数\naggs = [\n    pl.col(\"index\").count().alias(\"index_count\"),\n    *[pl.col(c).sum().alias(f\"{c}_sum\") for c in nums],\n    *[pl.col(c).mean().alias(f\"{c}_mean\") for c in nums],\n    *[pl.col(c).std().alias(f\"{c}_std\") for c in nums],\n]\n\n# 実行処理部分\ndisplay(\n    pl_df\n    .group_by(\"session_id\", maintain_order=True)\n    .agg(aggs)\n    .sort(\"index_count\")\n    .head()\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:28:16.237391Z","iopub.execute_input":"2026-02-24T23:28:16.237776Z","iopub.status.idle":"2026-02-24T23:28:17.711059Z","shell.execute_reply.started":"2026-02-24T23:28:16.237751Z","shell.execute_reply":"2026-02-24T23:28:17.709893Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# event_nameの水準取得\nevent_names = pl_df.get_column(\"event_name\").unique(maintain_order=True).to_list()\nprint(event_names)\n\n# 集約したい変数リスト\nnums = [\"elapsed_time\", \"index\", \"fullscreen\", \"hq\", \"music\"]\n# aggに渡す引数\naggs = [\n    pl.col(\"index\").count().alias(\"index_count\"),\n    # 列が多すぎるためコメントアウト\n    # *[pl.col(c).sum().alias(f\"{c}_sum\") for c in nums],\n    # *[pl.col(c).mean().alias(f\"{c}_mean\") for c in nums],\n    # *[pl.col(c).std().alias(f\"{c}_std\") for c in nums],\n    *[pl.col(\"index\").filter(pl.col(\"event_name\") == v).count().alias(f\"{v}_count\") for v in event_names],\n]\n\n# 実行処理部分\ndisplay(\n    pl_df\n    .group_by(\"session_id\")\n    .agg(aggs)\n    .sort(\"index_count\")\n    .head()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:32:06.203474Z","iopub.execute_input":"2026-02-24T23:32:06.204190Z","iopub.status.idle":"2026-02-24T23:32:08.543242Z","shell.execute_reply.started":"2026-02-24T23:32:06.204162Z","shell.execute_reply":"2026-02-24T23:32:08.542512Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# event_nameの水準取得\nevent_names = pl_df.get_column(\"event_name\").unique(maintain_order=True).to_list()\n\n# 集約したい変数リスト\nnums = [\"elapsed_time\", \"index\", \"fullscreen\", \"hq\", \"music\"]\n# aggに渡す引数\naggs = [\n    pl.col(\"index\").count().alias(\"index_count\"),\n    # 列が多すぎるためコメントアウト\n    # *[pl.col(c).sum().alias(f\"{c}_sum\") for c in nums],\n    # *[pl.col(c).mean().alias(f\"{c}_mean\") for c in nums],\n    # *[pl.col(c).std().alias(f\"{c}_std\") for c in nums],\n    # *[pl.col(\"index\").filter(pl.col(\"event_name\") == v).count().alias(f\"{v}_count\") for v in event_names],\n    *[pl.col(c).filter(pl.col(\"event_name\")==v).sum().alias(f\"{c}_{v}_sum\") for c in nums for v in event_names]\n]\n\n# 実行処理部分\ndisplay(\n    pl_df\n    .group_by(\"session_id\")\n    .agg(aggs)\n    .sort(\"index_count\")\n    .head()\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-24T23:31:58.134477Z","iopub.execute_input":"2026-02-24T23:31:58.135720Z","iopub.status.idle":"2026-02-24T23:32:06.201702Z","shell.execute_reply.started":"2026-02-24T23:31:58.135673Z","shell.execute_reply":"2026-02-24T23:32:06.200533Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}