Python Pandasの辞書式順序スライスでデータのサブセットを抽出する方法
はじめに
Pandasには、インデックス位置またはインデックスラベルを使ってデータのサブセットを選択する、2つの選択手段が用意されています。本記事では、その中でも「辞書式順序スライス(lexicographical slicing)」を使ってデータのサブセットを抽出する方法を解説します。
インターネット上にはさまざまなデータセットが公開されています。今回はKaggle(kaggle.com)で公開されている映画データセットを使用します。
準備:必要な列だけを読み込む
まず、この例に必要な列だけを指定して映画データセットを読み込みます。インデックスには映画タイトル(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 |
インデックスは必ずソートしておく
特にインデックスが文字列で構成されている場合は、あらかじめインデックスをソートしておくことを強くお勧めします。大規模なデータセットを扱う際に、その違いを実感できるはずです。
インデックスをソートしないとどうなるのか?
「コードが永遠に実行され続ける」――なんて冗談はさておき、インデックスラベルがソートされていない場合、Pandasは条件に一致するラベルを探すために、すべてのラベルを先頭から1つずつ順番に走査しなければなりません。
索引ページのないオックスフォード英辞典を想像してみてください。目的の単語を調べるのに、ページを最初から順にめくっていくしかありませんよね。インデックスがソートされていれば、目的のラベルへ一気にジャンプできます。Pandasの内部動作もまったく同じです。
それでは、まず現在のインデックスがソート済みかどうかを確認してみましょう。
# インデックスがソートされているか確認
movies.index.is_monotonic実行結果:
False※ 補足:新しいバージョンのPandasでは is_monotonic は非推奨となっており、代わりに is_monotonic_increasing の使用が推奨されています。
明らかに、インデックスはソートされていません。この状態で「A」で始まる映画タイトルだけを抽出してみます。SQLで書くと、次のようなイメージです。
SELECT * FROM movies WHERE title LIKE 'A%'これをPandasの loc を使ったスライスで表現すると、次のようになります。
movies.loc["Aa":"Bb"]しかし、このコードはエラーになります。
ValueError: index must be monotonic increasing or decreasing
...
KeyError: 'Aa'「index must be monotonic increasing or decreasing(インデックスは単調増加または単調減少である必要があります)」というエラーが発生しました。ソートされていないインデックスに対しては、辞書式順序スライスが使えないのです。
インデックスをソートして再挑戦
そこで、インデックスを昇順にソートしてから、同じ操作をもう一度試してみましょう。
# インデックスを昇順にソート
movies = movies.sort_index()
# もう一度確認
movies.index.is_monotonic実行結果:
Trueこれでデータの準備が整い、辞書式順序スライスが使えるようになりました。それでは、「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 |
292行 × 3列 の結果が得られました。
降順ソートされたデータの場合
データが降順にソートされている場合はどうなるでしょうか。この状態で通常どおりにスライスすると、空のDataFrameが返されます。データが逆順に並んでいるため、これはごく自然な結果です。
解決策は簡単です。開始と終了のラベルを逆に指定すればOKです。
movies.loc["Bb":"Aa"]| 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 |
228行 × 3列 の結果が得られました。
まとめ
- 文字列のインデックスに対しては、事前にソートしておくことで高速な検索が可能になる
- ソートされていないインデックスでスライスしようとすると
ValueErrorが発生する - 降順ソートされたデータの場合は、開始・終了のラベルを逆に指定する
-
【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