想像してみてください。顧客データ分析で、購入履歴のない大量のデータや、住所が未入力のデータがそのまま含まれていたら、分析結果が実態と大きく乖離してしまうかもしれません。分析の精度が落ち、誤った意思決定につながるリスクさえあります。
なぜなら、不要なデータを適切に削除することは、正確で信頼性の高い分析結果を得るための土台となるからです。
そこで強力な味方となるのが、Pandasのデータ削除メソッドです。これらのメソッドを使うことで、データフレームから特定の行や列を柔軟に、そして効率的に削除できます。この記事では、データの前処理に必須のdrop()
、dropna()
、drop_duplicates()
といったメソッドについて、基本から応用、そして関連メソッドまで、初心者の方にも分かりやすく解説します。
この記事を読めば、あなたのデータセットから不要な部分を自信を持って削除できるようになります。データ分析の質を高めるための第一歩を、ここで踏み出しましょう!
▶️ drop等の公式ドキュメントも参考にしてください:
- pandas DataFrame drop Documentation
- pandas DataFrame dropna Documentation
- pandas DataFrame drop_duplicates Documentation
サンプルデータの作成
まずはサンプルデータを作成しましょう。今回は、より現実的なデータとしてseabornライブラリに含まれるタイタニックデータの一部を利用します。
from IPython import get_ipython
from IPython.display import display # データフレームを見やすく表示するために使用
import pandas as pd
import seaborn as sns # サンプルデータのためにインポート
# タイタニックデータセットをロードし、必要な列に絞り、一部欠損値を意図的に作成します
df = sns.load_dataset('titanic') # より現実的なサンプルデータ(タイタニックデータの一部を利用)
df = df[['survived', 'pclass', 'sex', 'age', 'fare', 'embarked']].head(10) # 今回の解説に必要な列に絞り、一部欠損値を意図的に作成
df.loc[[1, 3], 'age'] = None # ageに欠損値をいくつか作成
df.loc[7, 'embarked'] = None # embarkedに欠損値をいくつか作成
df.loc[8, 'fare'] = None # fareに欠損値をいくつか作成
print("元のデータ(一部):")
display(df)
元のデータ(一部):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 7.2500 | S |
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
上記のデータフレームを使って、drop()メソッドの使い方を学んでいきましょう
Pandasデータ削除の基本:drop()メソッド
drop()
メソッドは、データフレームから指定した行や列を削除するために使用します。最も基本的な削除方法を学びましょう。
基本的な構文は以下の通りです。
df.drop(labels, axis=0 or 1, inplace=False, errors='raise')
主要な引数は以下の通りです。
labels
: 削除したい行(インデックス)や列(列名)を指定します。単一の値、またはリストで指定できます。axis
: 削除の方向を指定します。0
または'index'
で行を削除、1
または'columns'
で列を削除します。inplace
:True
なら元のデータフレームを直接変更します。デフォルトはFalse
で、変更を反映した新しいデータフレームを返します。errors
: 削除しようとしたラベルが存在しない場合の挙動を指定します。'raise'
(デフォルト)ならエラーが発生し、'ignore'
ならエラーを発生させずにスキップします。
📌行の削除方法(axis=0)
axis=0またはaxis=’index’を指定すると、指定したインデックスの行を削除できます。
例として、インデックスが1の行を削除してみましょう。inplace=Falseのため、元のデータフレームは変更されずに新しいデータフレームが返されます。
# インデックス1の行を削除(元のデータフレームは変更されない)
df_dropped_row = df.drop(labels=1, axis=0, inplace=False)
print("インデックス1を削除したデータフレーム:")
display(df_dropped_row)
print("\n元のデータフレーム(変更なし):")
display(df)
インデックス1を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 7.2500 | S |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
元のデータフレーム(変更なし):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 7.2500 | S |
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
コードの解説:
- df.drop(labels=1, axis=0, inplace=False): データフレームdfから、labels=1(インデックスが1の行)を、axis=0(行方向)に削除します。inplace=Falseなので、この操作による変更は新しいデータフレームdf_dropped_rowに反映され、元のdfはそのまま残ります。
📌列の削除方法(axis=1)
axis=1またはaxis=’columns’を指定すると、指定した列名の列を削除できます。
例として、’survived’列を削除してみましょう。こちらもinplace=Falseのため、元のデータフレームは変更されません。
# 'survived'列を削除(元のデータフレームは変更されない)
# labelsとaxis=1を使用して列を指定します
df_dropped_col = df.drop(labels="survived", axis=1, inplace=False)
print("'survived'列を削除したデータフレーム:")
display(df_dropped_col)
print("\n元のデータフレーム(変更なし):")
display(df)
survived列を削除したデータフレーム:
pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|
0 | 3 | male | 22.0 | 7.2500 | S |
1 | 1 | female | NaN | 71.2833 | C |
2 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | female | NaN | 53.1000 | S |
4 | 3 | male | 35.0 | 8.0500 | S |
5 | 3 | male | NaN | 8.4583 | Q |
6 | 1 | male | 54.0 | 51.8625 | S |
7 | 3 | male | 2.0 | 21.0750 | None |
8 | 3 | female | 27.0 | NaN | S |
9 | 2 | female | 14.0 | 30.0708 | C |
元のデータフレーム(変更なし):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 7.2500 | S |
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
コードの解説:
- df.drop(labels=survived”, axis=1, inplace=False): データフレームdfから、lables=”survived”(列名が’survived’の列)を、axis=1(列方向)に削除します。inplace=Falseなので、新しいデータフレームdf_dropped_colが生成され、元のdfは変更されません。
⚠️ inplace=Trueで元のDataFrameを変更
inplace=True を指定すると、drop() メソッドは、データフレームを新しいものとして作り直すのではなく、元のデータフレームそのものに直接、削除の変更を加えます。
例えるなら、書類をコピーして修正する(inplace=False)のではなく、原本の書類に直接ペンで書き込み、修正部分を消しゴムで消す(inplace=True)イメージです。
そのため、一度 inplace=True で変更すると、元のデータフレームは削除された状態で上書きされてしまい、削除前の状態に戻すことは基本的にできません。この点は特に注意が必要です。
# インデックス0の行を削除(元のデータフレームが直接変更される)
df.drop(labels=0, axis=0, inplace=True)
print("inplace=True の場合(元のデータフレームが変更される):")
display(df) # 元のdf自体が変更されています
inplace=True の場合(元のデータフレームが変更される):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
コードの解説:
- df.drop(labels=0, axis=0, inplace=True): インデックス0の行が、元のデータフレームdfから直接削除されます。この操作の戻り値はNoneです。
ポイント: inplace=Trueを指定すると、戻り値はNoneで、df自体が変更されます。したがって、df = df.drop(…)のように代入する必要はありません。元のデータを残しておきたい場合は、必ずinplace=False(または省略)にして、新しいデータフレームとして受け取るようにしましょう。
🧠 よくあるエラーと注意点
drop()メソッドを使用する際によく遭遇するエラーと、いくつかの注意点を確認しておきましょう。
- KeyError: 存在しないラベル(インデックスや列名)を削除しようとすると発生します。
- inplace=Trueを使うと、元のデータフレームが変更され、戻り値はNoneになります。
- inplace=Trueを使うと元のデータフレームが失われるため、慎重に使用する必要があります。特に、後続の処理で元のデータが必要な場合は、inplace=Falseを使用しましょう。
削除するラベルが存在しない場合
デフォルトでは、指定したラベルが存在しない場合 KeyError が発生します。errors=’ignore’ を指定することで、エラーを無視して処理を続行できます。errors=’ignore’ は、「存在するなら削除、なければスルーしたい」という場面では非常に有用です。特に、柔軟なコードや自動化された処理を組むときには欠かせません。
# 存在しない列 'non_existent_col' を削除しようとする (エラーが発生)
try:
print("存在しない列を削除しようとしています (errors='raise'):")
df.drop(labels='non_existent_col', axis=1, errors='raise')
except KeyError as e:
print(f"エラーが発生しました: {e}")
print("-" * 30) # 区切り線
# 存在しない列 'non_existent_col' を削除しようとする (errors='ignore' でエラーを無視)
print("存在しない列を削除しようとしています (errors='ignore'):")
df_ignored_error = df.drop(labels='non_existent_col', axis=1, errors='ignore')
print("errors='ignore' を指定した場合のデータフレーム(エラーは発生しません):")
display(df_ignored_error)
存在しない列を削除しようとしています (errors='raise'): エラーが発生しました: "['non_existent_col'] not found in axis"
——————————存在しない列を削除しようとしています (errors='ignore'): errors='ignore' を指定した場合のデータフレーム(エラーは発生しません):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
コードの解説:
- 最初のtry…exceptブロックでは、存在しない列名’non_existent_col’を削除しようとしています。デフォルトのerrors=’raise’のため、KeyErrorが発生し、そのエラーメッセージが表示されます。
- 次のコードでは、同じように存在しない列名を削除しようとしていますが、errors=’ignore’を指定しています。この場合、エラーは発生せず、指定したラベルが存在しなかった場合は単にスキップされます。元のデータフレームdf(既にインデックス0の行が削除されています)が表示されますが、指定した列が存在しないため、何も変更されていません。
💡 複数行・複数列を削除する方法
labels
引数には、削除したいインデックスや列名をリスト形式で指定できます。
# 複数行(インデックス1と2)を削除(元のデータフレームは変更されない)※ここでは、上記でインデックス0を削除した後のdfに対して操作を行います。
# 削除前のデータフレームを表示
print("削除前のデータフレーム:")
display(df)
df_dropped_rows = df.drop(labels=[1, 2], axis=0, inplace=False)
print("\n複数行を削除したデータフレーム:")
display(df_dropped_rows)
削除前のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
複数行を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
# 複数列('survived'と'pclass')を削除(元のデータフレームは変更されない)
# ※ここでは、前に行った行削除の操作後のdfに対して操作を行います。
# 削除前のデータフレームを表示
print("削除前のデータフレーム:")
display(df)
# 複数列を削除
# labelsに列名のリストを指定し、axis=1とinplace=Falseを使用
df_dropped_cols = df.drop(labels=['survived', 'pclass'], axis=1, inplace=False)
print("\n複数列を削除したデータフレーム:")
display(df_dropped_cols)
削除前のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
複数列を削除したデータフレーム:
sex | age | fare | embarked | |
---|---|---|---|---|
1 | female | NaN | 71.2833 | C |
2 | female | 26.0 | 7.9250 | S |
3 | female | NaN | 53.1000 | S |
4 | male | 35.0 | 8.0500 | S |
5 | male | NaN | 8.4583 | Q |
6 | male | 54.0 | 51.8625 | S |
7 | male | 2.0 | 21.0750 | None |
8 | female | 27.0 | NaN | S |
9 | female | 14.0 | 30.0708 | C |
コードの解説:
- df.drop(labels=[‘survived’, ‘pclass’], axis=1, inplace=False): labelsに列名のリスト[‘survived’, ‘pclass’]を指定することで、’survived’列と’pclass’列の両方を削除した新しいデータフレームを作成します。
✨ 応用例: より柔軟に!条件を指定して行を削除する方法
「データ分析では、『特定の条件を満たすデータだけを処理したい』『ある条件に該当する行は除外したい』といった場面が頻繁にあります。Pandasでは、条件を指定して削除したい行を絞り込み、その結果のインデックスをdrop()メソッドに渡すことで、柔軟なデータ削除が可能です。」
「ここでは、具体的な例を通してその手順を見ていきましょう。」
例1:年齢が20歳未満かつ性別が女性の乗客の行を削除
条件に一致する行をデータフレームのインデックスで抽出し、そのインデックスをdrop()に渡します。
# 条件を指定して行を削除する方法
# 削除前のデータフレームを表示
print("元のデータフレーム:")
display(df)
# 年齢が20歳未満かつ性別が女性の行を抽出します。
# この条件に一致する行のインデックスを取得します。
index_to_drop_multi = df[(df['age'] < 20) & (df['sex'] == 'female')].index
print(f"\n削除対象となる行のインデックス: {index_to_drop_multi.tolist()}")
# 取得したインデックスの行を削除します。
df_no_young_female = df.drop(index=index_to_drop_multi, axis=0)
print("\n年齢が20歳未満かつ性別が女性の行を削除したデータフレーム:")
display(df_no_young_female)
元のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
削除対象となる行のインデックス: [9]
年齢が20歳未満かつ性別が女性の行を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
コードの解説:
- df[(df[‘age’] < 20) & (df[‘sex’] == ‘female’)]: この部分で、「ageが20未満」かつ「sexがfemale」という条件を満たす行をデータフレームdfから抽出しています。
- .index: 抽出された行のインデックスを取得しています。
- df.drop(index=index_to_drop_multi, axis=0): 取得したインデックスを指定して、これらの行を元のデータフレームdfから削除しています。index=引数を使うことで、削除したいインデックスを直接指定できます。
例2: query() メソッドの利用例:
query() メソッドを使うと、より直感的に条件を記述できます。条件に一致する行を抽出し、そのインデックスをdrop()に渡す方法は同じです。
# query() メソッドを使って年齢が20歳未満の行を抽出します。
# 削除前のデータフレームを表示
print("元のデータフレーム:")
display(df)
# 条件に一致する行のインデックスを取得します。
index_to_drop_query = df.query('age < 20').index
print(f"\nquery()で抽出した削除対象となる行のインデックス: {index_to_drop_query.tolist()}") # 改行を追加して見やすく
# 取得したインデックスの行を削除します。
df_no_young_query = df.drop(index=index_to_drop_query, axis=0)
print("\nquery() を使って年齢が20歳未満の行を削除したデータフレーム:")
display(df_no_young_query)
元のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
query()で抽出した削除対象となる行のインデックス: [7, 9]
query() を使って年齢が20歳未満の行を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
8 | 1 | 3 | female | 27.0 | NaN | S |
コードの解説:
- df.query(‘age < 20’): query()メソッドを使って、「ageが20未満」という条件を満たす行を抽出しています。文字列で条件式を記述できるため、可読性が高い場合が多いです。
- .index: 抽出された行のインデックスを取得しています。
- df.drop(index=index_to_drop_query, axis=0): 取得したインデックスを指定して、これらの行を元のデータフレームdfから削除しています。
補足: さらに複雑な条件(例: 特定の値のリストに含まれるか、文字列の一部を含むかなど)で削除したい場合も、同様に条件に一致する行のインデックスを取得し、drop()に渡すことで対応できます。
例3: 特定の値リストに含まれるカテゴリの行を削除
drop()
と条件指定を組み合わせることで、「特定の列の値が、指定したリストに含まれている行」を削除することも簡単にできます。例えば、特定の港(embarked
)から乗船した乗客のデータを除外したい場合に役立ちます。
ここでは、港(embarked
)が ‘C’ または ‘Q’ の乗客の行を削除してみましょう。isin()
メソッドを使って条件を指定します。
print("元のデータフレーム:")
display(df) # この時点でのdfを表示
# embarked が 'C' または 'Q' の行を抽出します。
# この条件に一致する行のインデックスを取得します。
index_to_drop_embark = df[df['embarked'].isin(['C', 'Q'])].index
print(f"\n'C' または 'Q' の港から乗船した乗客のインデックス: {index_to_drop_embark.tolist()}")
# 取得したインデックスの行を削除します。
df_no_C_Q = df.drop(index=index_to_drop_embark, axis=0)
print("\n'C' または 'Q' の港から乗船した乗客の行を削除したデータフレーム:")
display(df_no_C_Q)
元のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
'C' または 'Q' の港から乗船した乗客のインデックス: [1, 5, 9]
'C' または 'Q' の港から乗船した乗客の行を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
コードの解説:
df['embarked'].isin(['C', 'Q'])
:embarked
列の値がリスト['C', 'Q']
のいずれかに含まれているかどうかを判定しています。結果はTrue/Falseのシリーズになります。df[...]
: このTrue/Falseのシリーズを使って、条件に一致する行をデータフレームdf
から抽出しています。.index
: 抽出された行のインデックスを取得しています。df.drop(index=index_to_drop_embark, axis=0)
: 取得したインデックスを指定して、これらの行を元のデータフレームdf
から削除しています。【なぜ条件削除が重要か】
このように条件を指定して不要な行を削除することは、特定のグループを除外して分析したい場合や、外れ値やエラーデータを取り除きたい場合に非常に有効です。これにより、よりターゲットを絞った、あるいはよりクリーンなデータセットで分析を進めることができます。
関連メソッド:欠損値や重複行の削除
「データ削除には、drop()メソッド以外にも、特定の目的で非常に便利なメソッドが存在します。特に、データ前処理で頻繁に遭遇する『欠損値』や『重複データ』の扱いに特化したメソッドは、効率的なデータクリーニングに役立ちます。」
「ここでは、dropna()とdrop_duplicates()という2つの重要なメソッドをご紹介します。」
👩💻 欠損値を含む行・列の削除:dropna()
dropna()
メソッドは、データフレームから欠損値(NaNやNone)を含む行または列を削除するために使用します。
基本的な構文は以下の通りです。
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
主要な引数は以下の通りです。
axis
: 削除の方向を指定します。0
または'index'
で欠損値を含む行を削除(デフォルト)、1
または'columns'
で欠損値を含む列を削除します。how
: 欠損値がどの程度存在する場合に削除するかを指定します。'any'
(デフォルト)は、指定した方向に1つでも欠損値があれば削除します。'all'
は、指定した方向の全ての値が欠損値の場合にのみ削除します。thresh
: 指定した方向に、欠損値以外の値がこの数以上ある場合は削除しません。(この数未満の非欠損値の行/列を削除します)subset
: 欠損値を検出する対象を、特定の列(または列のリスト)に限定します。inplace
:True
なら元のデータフレームを直接変更します。デフォルトはFalse
で、変更を反映した新しいデータフレームを返します。
元のデータフレームには欠損値が含まれています。dropna()
で欠損値を含む行、列を削除してみましょう。
# 欠損値を含む行の削除例
# --- 削除前の元のデータフレームを表示 ---
print("元のデータフレーム:")
display(df)
print("\n--- 各行の欠損値の数(参考情報)---")
display(df.isnull().sum(axis=1))
# --- 欠損値を含む行を削除 ---
print("\n--- 欠損値を含む行を削除 ---")
# 欠損値を含む行を削除します(元のデータフレームは変更されない)
# axis=0 はデフォルトなので省略可能ですが、ここでは明示的に指定します
# how='any' もデフォルトなので省略可能ですが、ここでは明示的に指定します
df_dropna_rows = df.dropna(axis=0, how='any')
print("欠損値を含む行を削除したデータフレーム:")
display(df_dropna_rows)
元のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
— 各行の欠損値の数(参考情報)—
0 | |
---|---|
1 | 1 |
2 | 0 |
3 | 1 |
4 | 0 |
5 | 1 |
6 | 0 |
7 | 1 |
8 | 1 |
9 | 0 |
— 欠損値を含む行を削除 — 欠損値を含む行を削除したデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
# 欠損値を含む列の削除例
# --- 削除前の元のデータフレームを表示 ---
print("元のデータフレーム:")
display(df) # 列を削除する前の df を表示
print("\n--- 各列の欠損値の数(参考情報)---")
display(df.isnull().sum()) # 参考情報として、欠損値の数も再度表示しておきます
# --- 欠損値を含む列を削除 ---
print("\n--- 欠損値を含む列を削除 ---")
# 欠損値を含む列を削除します(元のデータフレームは変更されない)
df_dropna_cols = df.dropna(axis=1)
print("欠損値を含む列を削除したデータフレーム:")
display(df_dropna_cols)
元のデータフレーム:
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
1 | 1 | 1 | female | NaN | 71.2833 | C |
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
— 各列の欠損値の数(参考情報)—
0 | |
---|---|
survived | 0 |
pclass | 0 |
sex | 0 |
age | 3 |
fare | 1 |
embarked | 1 |
— 欠損値を含む列を削除 — 欠損値を含む列を削除したデータフレーム:
survived | pclass | sex | |
---|---|---|---|
1 | 1 | 1 | female |
2 | 1 | 3 | female |
3 | 1 | 1 | female |
4 | 0 | 3 | male |
5 | 0 | 3 | male |
6 | 0 | 1 | male |
7 | 0 | 3 | male |
8 | 1 | 3 | female |
9 | 1 | 2 | female |
📝 重複行の削除:drop_duplicates()
drop_duplicates()
メソッドは、完全に重複している行を削除します。
サンプルデータには重複行がないため、簡単な重複データを作成して試してみましょう。
# 重複データを含むサンプルデータフレームを作成
data = {'col1': ['A', 'B', 'A', 'C', 'B'],
'col2': [1, 2, 1, 3, 2]}
df_dup = pd.DataFrame(data)
print("重複データを含むデータフレーム:")
display(df_dup)
# 重複行を削除(元のデータフレームは変更されない)
df_no_dup = df_dup.drop_duplicates()
print("重複行を削除したデータフレーム:")
display(df_no_dup)
重複データを含むデータフレーム:
col1 | col2 | |
---|---|---|
0 | A | 1 |
1 | B | 2 |
2 | A | 1 |
3 | C | 3 |
4 | B | 2 |
重複行を削除したデータフレーム:
col1 | col2 | |
---|---|---|
0 | A | 1 |
1 | B | 2 |
3 | C | 3 |
🔄 インデックスのリセット:reset_index()
データフレームから行を削除したり、特定の操作(例: グループ化後の集約など)を行ったりすると、元のインデックスが維持されずに飛び飛びになったり、特別な意味を持つインデックスになったりすることがあります。このような場合に、インデックスをリセットして0から始まる新しい連番のインデックスを振り直したいことがあります。その際に使用するのが reset_index()
メソッドです。
基本的な構文は以下の通りです。
df.reset_index(level=None, drop=False, inplace=False, allow_duplicates=False, name=None)
主要な引数は以下の通りです。
level
: MultiIndex(階層的なインデックス)の場合に、どのレベルのインデックスをリセットするかを指定します。drop
:True
を指定すると、元のインデックスを破棄します。デフォルトはFalse
で、元のインデックスは新しい列としてデータフレームに追加されます。inplace
:True
なら元のデータフレームを直接変更します。デフォルトはFalse
です。name
: 新しいインデックス列の名前を指定します。
例として、インデックスが飛び飛びになったデータフレームに対して reset_index()
を適用してみましょう。(ここでは、インデックス 0 が削除された状態の df
を使います。)
#現在の df は、インデックス 0 が削除された状態です。
print("現在のデータフレーム(インデックスが飛び飛び):")
df.drop(index=1,axis=0,inplace=True)
#インデックス 1 を削除した df を使用
display(df)
#reset_index() を適用(元のインデックスを新しい列として保持)
df_reset = df.reset_index()
print("\nreset_index() を適用したデータフレーム(元のインデックスが列になる):")
display(df_reset)
#reset_index(drop=True) を適用(元のインデックスを破棄)
df_reset_drop = df.reset_index(drop=True)
print("\nreset_index(drop=True) を適用したデータフレーム(元のインデックスを破棄):")
display(df_reset_drop)
現在のデータフレーム(インデックスが飛び飛び):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
2 | 1 | 3 | female | 26.0 | 7.9250 | S |
3 | 1 | 1 | female | NaN | 53.1000 | S |
4 | 0 | 3 | male | 35.0 | 8.0500 | S |
5 | 0 | 3 | male | NaN | 8.4583 | Q |
6 | 0 | 1 | male | 54.0 | 51.8625 | S |
7 | 0 | 3 | male | 2.0 | 21.0750 | None |
8 | 1 | 3 | female | 27.0 | NaN | S |
9 | 1 | 2 | female | 14.0 | 30.0708 | C |
reset_index() を適用したデータフレーム(元のインデックスが列になる):
index | survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|---|
0 | 2 | 1 | 3 | female | 26.0 | 7.9250 | S |
1 | 3 | 1 | 1 | female | NaN | 53.1000 | S |
2 | 4 | 0 | 3 | male | 35.0 | 8.0500 | S |
3 | 5 | 0 | 3 | male | NaN | 8.4583 | Q |
4 | 6 | 0 | 1 | male | 54.0 | 51.8625 | S |
5 | 7 | 0 | 3 | male | 2.0 | 21.0750 | None |
6 | 8 | 1 | 3 | female | 27.0 | NaN | S |
7 | 9 | 1 | 2 | female | 14.0 | 30.0708 | C |
reset_index(drop=True) を適用したデータフレーム(元のインデックスを破棄):
survived | pclass | sex | age | fare | embarked | |
---|---|---|---|---|---|---|
0 | 1 | 3 | female | 26.0 | 7.9250 | S |
1 | 1 | 1 | female | NaN | 53.1000 | S |
2 | 0 | 3 | male | 35.0 | 8.0500 | S |
3 | 0 | 3 | male | NaN | 8.4583 | Q |
4 | 0 | 1 | male | 54.0 | 51.8625 | S |
5 | 0 | 3 | male | 2.0 | 21.0750 | None |
6 | 1 | 3 | female | 27.0 | NaN | S |
7 | 1 | 2 | female | 14.0 | 30.0708 | C |
✅ まとめ
この記事を通して、あなたはPandasのデータフレームから不要な行や列を削除する、非常に重要なスキルを習得しました。データ分析の質と効率を大きく左右する、この「削除」という操作について、drop()
メソッドを中心に、基本から応用、そして関連メソッドまでを網羅的に学びました。
具体的には、
- 指定したラベルに基づいて行(
axis=0
)や列(axis=1
)を柔軟に削除できるdrop()
メソッドの基本的な使い方。 - 元のデータフレームを直接変更するかどうかをコントロールする
inplace
引数の重要性とその使い分け。 - 存在しないラベルの削除時にエラーを無視できる
errors='ignore'
の便利な機能。 - 複数行や複数列を一度に削除する方法。
- 特定の条件(例えば「年齢が20歳未満」や「性別が女性」など)を満たす行だけを削除するための、条件指定と
drop()
の組み合わせ方。特に、より直感的に条件を記述できるquery()
メソッドの活用例もご紹介しました。
さらに、特定の目的(欠損値や重複データ)に特化した便利なメソッドとして、
- 欠損値を含む行や列を簡単に削除できる
dropna()
メソッド。 - 完全に重複している行を効率的に削除できる
drop_duplicates()
メソッド。
についても理解を深めました。drop()
がラベルに基づいて削除するのに対し、dropna()
やdrop_duplicates()
はデータの「値」や「状態」に基づいて削除するという違いも押さえたはずです。
これらの削除メソッドは、データフレームを整形し、その後の分析や可視化、機械学習モデルの構築など、あらゆるデータ活用のステップにおいて不可欠な前処理スキルです。分析に不要なデータを取り除くことで、メモリ使用量を削減し、処理速度を向上させ、何よりもより正確で信頼性の高い分析結果を得ることができます。
さあ、今日学んだことを活かして、ぜひあなたのお手元にあるデータセットで実際にコードを実行してみてください。きっと、データが分析に適した形になっていくのを実感できるはずです。
データ前処理の旅はまだ始まったばかりです。次には、削除したデータの「欠損値」をどのように補完するのか、あるいはデータの「型変換」をどう行うのかなど、学ぶべきことがたくさんあります。これらのスキルを一つずつ習得していくことで、あなたはデータ分析の達人への道を確実に進んでいくでしょう。
この記事が、あなたのデータ前処理の強力な一助となれば幸いです!
⚠️データ削除全般に関わるリスク
これらの強力な削除メソッドを使いこなす一方で、最も重要な点として認識しておきたいのは、「データを削除しないほうが良いケースがある」ということです。 安易なデータ削除は、分析の質を大きく損なうリスクを伴います。データ削除を検討する際は、常に以下のリスクと考慮事項を頭に入れましょう。
- 情報損失のリスク: 意図せず重要なデータまで削除してしまったり、将来の分析に必要なデータが失われたりする可能性があります。削除前にデータのバックアップを取ることを検討しましょう。
inplace=True
のリスク: この引数は元のデータフレームを直接変更し、一度実行すると元に戻すことが基本的にできません。元のデータを保持したい場合は、必ずinplace=False
を使用してください。- 欠損値や重複の背景、そして「削除しない」という選択肢の重要性:
dropna()
やdrop_duplicates()
を使う前に、なぜそのデータが欠損しているのか、なぜ重複しているのかといった背景を理解することが、データの本質を見誤らないために非常に重要です。時には、欠損値や重複を残したまま扱う(例:欠損値を特殊な値で埋める、重複の種類を分析するなど)方が、データが持つ本来の情報や構造を維持できる場合があります。また、一部の機械学習モデルは、欠損値をそのまま扱って高精度な予測を行うことが可能です。 単純な削除が最善策とは限りません。
賢くデータ削除を行うためのベストプラクティス(そして「削除しない」という選択肢も含めて考えるために):
- 削除する目的を明確にし、本当に削除が必要かを慎重に検討する。
- 削除対象のデータが全体のデータに与える影響を考慮し、削除によってデータの representativeness(代表性)が損なわれないかを確認する。
- 可能であれば削除前にデータのコピーを作成しておく。
- 欠損値や重複に対して、削除以外の代替策(補完、グルーピング、集計、または欠損値を扱えるモデルの利用など)がないかを検討する。
正確で信頼性の高い分析は、適切なデータ前処理から始まります。今回学んだ削除スキルを、そのメリットだけでなくリスクや代替策も含めて総合的に理解した上で活用してください。

コメント