Python Pandasの辞書式スライシングでデータのサブセットを抽出する方法を徹底解説
はじめに
Pandasには、インデックス位置(番号)またはインデックスラベル(文字列)を使ってデータのサブセットを選択できる、2つの選択機能が備わっています。本記事では、その中でも「辞書式スライシング(lexicographical slicing)」を使ってデータのサブセットを抽出する方法を詳しく解説します。
インターネット上には豊富なデータセットが公開されています。例えばkaggle.comで「movies dataset」と検索すると映画関連のデータセットが見つかります。本記事では、Kaggleの映画データセットを使用して説明していきます。
実装手順
1. データセットの読み込み
まず、この例に必要なカラムだけを指定して、映画データセットを読み込みます。ここでは「title」をインデックスとして設定しています。
import pandas as pd
import numpy as np
movies = pd.read_csv("https://raw.githubusercontent.com/sasankac/TestDataSet/master/movies_data.csv",index_col="title",
usecols=["title","budget","vote_average","vote_count"])
movies.sample(n=5)読み込んだデータは以下のようになります。
| title | budget | vote_average | vote_count |
|---|---|---|---|
| Little Voice | 0 | 6.6 | 61 |
| Grown Ups 2 | 80000000 | 5.8 | 1155 |
| The Best Years of Our Lives | 2100000 | 7.6 | 143 |
| Tusk | 2800000 | 5.1 | 366 |
| Operation Chromite | 0 | 5.8 | 29 |
2. インデックスをソートする重要性
特にインデックスが文字列で構成されている場合は、必ずインデックスをソートしておくことをおすすめします。大規模なデータセットを扱う場合、インデックスがソートされているかどうかで処理速度に大きな差が出ることに気づくでしょう。
インデックスをソートしないとどうなる?
もちろんコード自体は動きますが、インデックスラベルがソートされていない場合、Pandasはクエリに一致するラベルを見つけるために、すべてのラベルを1つずつ順番に走査しなければなりません。索引ページがないOxford辞典を想像してみてください。目的の単語を探すのに最初からページをめくるしかありませんよね。インデックスがソートされていれば、目的のラベルへ素早くジャンプできます。Pandasも同じ仕組みです。
まず、現在のインデックスがソートされているかどうか確認してみましょう。
# インデックスがソートされているか確認 movies.index.is_monotonic False
3. ソートされていない状態でのスライシングはエラーになる
結果はFalse。明らかにインデックスはソートされていません。この状態で、「A」で始まる映画タイトルを選択してみます。SQLで書くと次のようなイメージです。
select * from movies where title like 'A%'
Pandasでは以下のように記述します。
movies.loc["Aa":"Bb"]
しかし、このコードを実行するとエラーが発生します。
ValueError: index must be monotonic increasing or decreasing KeyError: 'Aa'
エラーメッセージにある通り、「index must be monotonic increasing or decreasing(インデックスは単調増加または単調減少である必要があります)」という例外が発生します。これが辞書式スライシングにはソート済みインデックスが必須である理由です。
4. インデックスを昇順にソートする
そこで、インデックスを昇順にソートしてから、同じコマンドを実行します。これにより、ソートの恩恵を受けた高速な辞書式スライシングが可能になります。
movies = movies.sort_index() movies.index.is_monotonic True
5. 辞書式スライシングの実行
これでデータの準備が整いました。「A」から「B」で始まるすべての映画タイトルを選択してみましょう。
movies.loc["A":"B"]
実行結果は以下の通りです。
| title | budget | vote_average | vote_count |
|---|---|---|---|
| Abandon | 25000000 | 4.6 | 45 |
| Abandoned | 0 | 5.8 | 27 |
| Abduction | 35000000 | 5.6 | 961 |
| Aberdeen | 0 | 7.0 | 6 |
| About Last Night | 12500000 | 6.0 | 210 |
| ... | ... | ... | ... |
| Battle for the Planet of the Apes | 1700000 | 5.5 | 215 |
| Battle of the Year | 20000000 | 5.9 | 88 |
| Battle: Los Angeles | 70000000 | 5.5 | 1448 |
| Battlefield Earth | 44000000 | 3.0 | 255 |
| Battleship | 209000000 | 5.5 | 2114 |
一方、降順にソートされたデータに対して「Aa」〜「Bb」のように昇順の範囲を指定すると、該当するデータが存在しないため空のDataFrameが返されます。
| title | budget | vote_average | vote_count |
|---|---|---|---|
| Æon Flux | 62000000 | 5.4 | 703 |
| xXx: State of the Union | 60000000 | 4.7 | 549 |
| xXx | 70000000 | 5.8 | 1424 |
| eXistenZ | 15000000 | 6.7 | 475 |
| [REC]² | 5600000 | 6.4 | 489 |
これは当然の結果です。データが逆順(降順)にソートされているためです。そこで、指定する文字の順序を逆にして再度実行してみましょう。
movies.loc["B":"A"]
今度は正しくデータが抽出されました。
| title | budget | vote_average | vote_count |
|---|---|---|---|
| B-Girl | 0 | 5.5 | 7 |
| Ayurveda: Art of Being | 300000 | 5.5 | 3 |
| Away We Go | 17000000 | 6.7 | 189 |
| Awake | 86000000 | 6.3 | 395 |
| Avengers: Age of Ultron | 280000000 | 7.3 | 6767 |
| ... | ... | ... | ... |
| About Last Night | 12500000 | 6.0 | 210 |
| Aberdeen | 0 | 7.0 | 6 |
| Abduction | 35000000 | 5.6 | 961 |
| Abandoned | 0 | 5.8 | 27 |
| Abandon | 25000000 | 4.6 | 45 |
まとめ
Pandasの辞書式スライシングを使えば、SQLのLIKE 'A%'のような前方一致検索を直感的に行えます。ただし重要なポイントとして、スライシングを行う前にインデックスを必ずソートしておく必要があります。ソートされていないインデックスに対してスライシングを実行するとエラーが発生し、また降順ソートの場合は開始・終了の指定順序にも注意が必要です。sort_index()とis_monotonicを活用して、効率的なデータ抽出を実現しましょう。
-
【Python・Pandas】Indexがカテゴリデータを保持しているかどうかを確認する方法
PandasのIndex(インデックス)がカテゴリ型(category)のデータを保持しているかどうかを確認するには、index.is_categorical()メソッドを使用します。この記事では、実際のコード例と出力結果をもとに、具体的な手順をわかりやすく解説します。 事前準備:ライブラリのインポート まず、必要なライブラリであるPandasをインポートします。 import pandas as pd カテゴリ型のIndexを作成する astype()メソッドを使うと、既存のIndexのデータ型を「category」に変換できます。ここでは、文字列のリストからカテゴリ型のPandasインデッ
-
【Python】Pandas DataFrameからサブセット(列の一部)を選択する方法
Pandas DataFrameのサブセット選択とは? Pandasでは、DataFrameから必要な列や行だけを取り出す操作を「サブセットの選択」と呼びます。大きなデータセットから目的のデータだけを抽出できれば、分析や前処理の効率が大幅に向上します。 この記事では、CSVファイルを読み込んだDataFrameから、1つの列、および複数の列を選択する基本的な方法を解説します。 使用するCSVファイルの内容 今回使用する「SalesData.csv」は、Microsoft Excelで開くと以下のような内容になっています。 CSVファイルからDataFrameを作成する まず、pd.rea