データ分析では、ただデータを見るだけでなく、特定の条件で並び替えることが非常に重要です。
たとえば「売上の高い順」「日付の新しい順」「名前の五十音順」など、並び順次第で読み取れる情報が変わることもあります。
並び替えが活躍する場面
- 売上ランキングの作成
- 時系列データの分析
- 異常値の発見
- レポート作成時の見やすい表示
Pythonのpandasでは、sort_values()
や sort_index()
を使って、簡単に並び替えができます。
この記事では、基本的な並び替えから、複数条件・インデックス単位の並び替えまでを実例付きでわかりやすく解説します。
pandasのDataFrameとは

まず、DataFrameについて簡単に説明します。
DataFrameの特徴
- 行と列からなる2次元のデータ構造
- Excelの表のようなイメージ
- 各列は異なるデータ型を持てる
サンプルデータの作成 この記事では、以下のような売上データを使って説明していきます:
import pandas as pd
# サンプルデータの作成
df = pd.DataFrame({
'名前': ['佐藤', '田中', '鈴木', '高橋', 'watanabe'],
'部署': ['営業', '開発', '営業', '人事', '開発'],
'売上': [5000, 3000, 7000, 4500, 6000],
'年齢': [25, 30, 35, 28, 32],
'入社日': ['2020-01-15', '2019-03-10', '2018-07-20', '2021-05-01', '2020-11-30']
})
# 入社日を日付型に変換
df['入社日'] = pd.to_datetime(df['入社日'])
print(df)
実行結果
名前 部署 売上 年齢 入社日
0 佐藤 営業 5000 25 2020-01-15
1 田中 開発 3000 30 2019-03-10
2 鈴木 営業 7000 35 2018-07-20
3 高橋 人事 4500 28 2021-05-01
4 watanabe 開発 6000 32 2020-11-30
sort_values()で列を並び替える基本
基本的な並び替え
最も基本的な並び替え方法は、一つの列を指定することです。
# 売上の昇順(小さい順)
df_asc = df.sort_values(by='売上')
print("売上昇順:")
print(df_asc)
実行結果
売上昇順:
名前 部署 売上 年齢 入社日
1 田中 開発 3000 30 2019-03-10
3 高橋 人事 4500 28 2021-05-01
0 佐藤 営業 5000 25 2020-01-15
4 watanabe 開発 6000 32 2020-11-30
2 鈴木 営業 7000 35 2018-07-20
降順での並び替え
売上の高い順(降順)で並び替えるには、ascending=False
を指定します:
# 売上の降順(大きい順)
df_desc = df.sort_values(by='売上', ascending=False)
print("売上降順:")
print(df_desc)
実行結果
売上降順:
名前 部署 売上 年齢 入社日
2 鈴木 営業 7000 35 2018-07-20
4 watanabe 開発 6000 32 2020-11-30
0 佐藤 営業 5000 25 2020-01-15
3 高橋 人事 4500 28 2021-05-01
1 田中 開発 3000 30 2019-03-10
文字列の並び替え
名前を五十音順で並び替えることもできます:
# 名前の五十音順
df_name = df.sort_values(by='名前')
print("名前順:")
print(df_name)
実行結果
名前順:
名前 部署 売上 年齢 入社日
4 watanabe 開発 6000 32 2020-11-30
0 佐藤 営業 5000 25 2020-01-15
2 鈴木 営業 7000 35 2018-07-20
3 高橋 人事 4500 28 2021-05-01
1 田中 開発 3000 30 2019-03-10
日付の並び替え
入社日で並び替えることで、古株から新人の順番がわかります:
# 入社日の昇順(古い順)
df_date = df.sort_values(by='入社日')
print("入社日順:")
print(df_date)
実行結果
入社日順:
名前 部署 売上 年齢 入社日
2 鈴木 営業 7000 35 2018-07-20
1 田中 開発 3000 30 2019-03-10
0 佐藤 営業 5000 25 2020-01-15
4 watanabe 開発 6000 32 2020-11-30
3 高橋 人事 4500 28 2021-05-01
基本的な並び替えができたら、次はより高度な複数条件での並び替えを見ていきましょう。
複数の列で並び替え(複数条件)

実際のデータ分析では、複数の条件で並び替えることがよくあります。例えば「部署ごとに分けて、その中で売上の高い順」といった具合です。
部署ごと・売上順の並び替え
# 部署の昇順、その中で売上の降順
df_multi = df.sort_values(by=['部署', '売上'], ascending=[True, False])
print("部署ごと売上順:")
print(df_multi)
実行結果
部署ごと売上順:
名前 部署 売上 年齢 入社日
4 watanabe 開発 6000 32 2020-11-30
1 田中 開発 3000 30 2019-03-10
2 鈴木 営業 7000 35 2018-07-20
0 佐藤 営業 5000 25 2020-01-15
3 高橋 人事 4500 28 2021-05-01
ポイント
by=['部署', '売上']
:最初に部署で並び替え、次に売上で並び替えascending=[True, False]
:部署は昇順、売上は降順
より複雑な条件での並び替え
# 部署昇順 → 年齢降順 → 売上昇順の順番で並び替え
df_complex = df.sort_values(
by=['部署', '年齢', '売上'],
ascending=[True, False, True]
)
print("複雑な条件での並び替え:")
print(df_complex)
実用的な例:成績表の並び替え
学校の成績表のような例で考えてみましょう:
# 成績データの作成
scores_df = pd.DataFrame({
'クラス': ['A', 'B', 'A', 'B', 'A', 'B'],
'名前': ['田中', '佐藤', '鈴木', '高橋', '渡辺', '山田'],
'数学': [85, 90, 78, 88, 92, 76],
'英語': [88, 85, 90, 87, 89, 83],
'国語': [90, 88, 85, 90, 87, 89]
})
# 合計点を計算
scores_df['合計'] = scores_df[['数学', '英語', '国語']].sum(axis=1)
# クラス別・合計点順で並び替え
scores_sorted = scores_df.sort_values(
by=['クラス', '合計'],
ascending=[True, False]
)
print("クラス別成績順:")
print(scores_sorted)
実行結果
クラス別成績順:
クラス 名前 数学 英語 国語 合計
4 A 渡辺 92 89 87 268
2 A 鈴木 78 90 85 253
0 A 田中 85 88 90 263
3 B 高橋 88 87 90 265
1 B 佐藤 90 85 88 263
5 B 山田 76 83 89 248
sort_index()でインデックス順に並び替え
sort_values()
が列の値で並び替えるのに対し、sort_index()
はインデックス(行番号)で並び替えます。
基本的なインデックス並び替え
# データを並び替えた後、インデックス順に戻す
df_shuffled = df.sort_values(by='売上', ascending=False)
print("売上順に並び替え後:")
print(df_shuffled)
df_index_sorted = df_shuffled.sort_index()
print("\nインデックス順に戻した後:")
print(df_index_sorted)
カスタムインデックスでの並び替え
# カスタムインデックスを設定
df_custom = df.copy()
df_custom.index = ['E001', 'E003', 'E002', 'E005', 'E004']
print("カスタムインデックス:")
print(df_custom)
# インデックスで並び替え
df_custom_sorted = df_custom.sort_index()
print("\nインデックス順:")
print(df_custom_sorted)
日付インデックスでの並び替え
時系列データでよく使われる例:
# 日付をインデックスに設定
df_date_index = df.set_index('入社日').sort_index()
print("入社日をインデックスにして並び替え:")
print(df_date_index)
並び替え後のインデックス処理
インデックスの振り直し
並び替え後は、元のインデックス番号が保持されるため、連番になっていません:
df_sorted = df.sort_values(by='売上', ascending=False)
print("並び替え後(インデックスそのまま):")
print(df_sorted)
# インデックスを振り直す
df_reset = df_sorted.reset_index(drop=True)
print("\nインデックス振り直し後:")
print(df_reset)
実行結果
並び替え後(インデックスそのまま):
名前 部署 売上 年齢 入社日
2 鈴木 営業 7000 35 2018-07-20
4 watanabe 開発 6000 32 2020-11-30
0 佐藤 営業 5000 25 2020-01-15
3 高橋 人事 4500 28 2021-05-01
1 田中 開発 3000 30 2019-03-10
インデックス振り直し後:
名前 部署 売上 年齢 入社日
0 鈴木 営業 7000 35 2018-07-20
1 watanabe 開発 6000 32 2020-11-30
2 佐藤 営業 5000 25 2020-01-15
3 高橋 人事 4500 28 2021-05-01
4 田中 開発 3000 30 2019-03-10
元のインデックスを保持する
元のインデックスを新しい列として保持したい場合:
df_with_original = df_sorted.reset_index()
print("元のインデックスを列として保持:")
print(df_with_original)
高度な並び替えテクニック

欠損値(NaN)の処理
# 欠損値を含むデータの作成
df_with_nan = df.copy()
df_with_nan.loc[1, '売上'] = None
df_with_nan.loc[3, '売上'] = None
print("欠損値を含むデータ:")
print(df_with_nan)
# 欠損値を最初に表示
df_nan_first = df_with_nan.sort_values(by='売上', na_position='first')
print("\n欠損値を最初に:")
print(df_nan_first)
# 欠損値を最後に表示
df_nan_last = df_with_nan.sort_values(by='売上', na_position='last')
print("\n欠損値を最後に:")
print(df_nan_last)
カスタムソート関数
key
パラメータを使用して、カスタムの並び替え条件を指定できます:
# 名前の長さで並び替え
df_name_length = df.sort_values(by='名前', key=lambda x: x.str.len())
print("名前の長さ順:")
print(df_name_length)
# 文字列を小文字にして並び替え(英語名がある場合)
df_case_insensitive = df.sort_values(by='名前', key=lambda x: x.str.lower())
print("\n大文字小文字を区別しない並び替え:")
print(df_case_insensitive)
条件付き並び替え
特定の条件を満たすデータのみを並び替える:
# 売上が5000以上のデータのみを並び替え
high_sales = df[df['売上'] >= 5000].sort_values(by='売上', ascending=False)
print("売上5000以上のデータを売上順:")
print(high_sales)
# 営業部門のデータのみを年齢順で並び替え
sales_dept = df[df['部署'] == '営業'].sort_values(by='年齢')
print("\n営業部門を年齢順:")
print(sales_dept)
数値的な並び替え
文字列として保存された数値を正しく並び替える:
# 文字列として保存された数値の例
df_str_numbers = pd.DataFrame({
'ID': ['1', '10', '2', '20', '3'],
'value': [100, 200, 150, 250, 175]
})
print("文字列として保存された数値:")
print(df_str_numbers)
# 文字列順で並び替え(間違った結果)
df_str_sort = df_str_numbers.sort_values(by='ID')
print("\n文字列として並び替え:")
print(df_str_sort)
# 数値として変換してから並び替え(正しい結果)
df_num_sort = df_str_numbers.sort_values(by='ID', key=lambda x: pd.to_numeric(x))
print("\n数値として並び替え:")
print(df_num_sort)
実践的な使用例
例1:売上レポートの作成
# より大きなサンプルデータ
sales_data = pd.DataFrame({
'営業担当': ['佐藤', '田中', '鈴木', '高橋', '山田', '佐藤', '田中', '鈴木'],
'月': [1, 1, 1, 1, 2, 2, 2, 2],
'売上': [100, 150, 120, 180, 110, 160, 140, 200],
'地域': ['東京', '大阪', '名古屋', '福岡', '東京', '大阪', '名古屋', '福岡']
})
# 月別・売上順でレポート作成
monthly_report = sales_data.sort_values(
by=['月', '売上'],
ascending=[True, False]
)
print("月別売上レポート:")
print(monthly_report)
# 営業担当別の合計売上でランキング作成
sales_ranking = sales_data.groupby('営業担当')['売上'].sum().sort_values(ascending=False)
print("\n営業担当別売上ランキング:")
print(sales_ranking)
例2:在庫管理システム
# 在庫データ
inventory = pd.DataFrame({
'商品名': ['商品A', '商品B', '商品C', '商品D', '商品E'],
'在庫数': [50, 5, 100, 2, 75],
'単価': [1000, 2000, 500, 3000, 1500],
'カテゴリ': ['電子機器', '家具', '文房具', '電子機器', '家具']
})
# 在庫数の少ない順で警告リスト作成
low_stock = inventory.sort_values(by='在庫数')
print("在庫警告リスト(在庫数順):")
print(low_stock)
# カテゴリ別・単価順で商品リスト作成
category_list = inventory.sort_values(
by=['カテゴリ', '単価'],
ascending=[True, False]
)
print("\nカテゴリ別商品リスト(単価順):")
print(category_list)
例3:学生成績の分析
# 学生成績データ
students = pd.DataFrame({
'学生ID': [1001, 1002, 1003, 1004, 1005],
'名前': ['田中', '佐藤', '鈴木', '高橋', '山田'],
'数学': [85, 92, 78, 88, 90],
'英語': [88, 85, 90, 87, 86],
'理科': [90, 88, 85, 92, 89],
'学年': [1, 2, 1, 2, 1]
})
# 総合点を計算
students['総合点'] = students[['数学', '英語', '理科']].sum(axis=1)
# 学年別・総合点順でランキング作成
ranking = students.sort_values(
by=['学年', '総合点'],
ascending=[True, False]
)
print("学年別成績ランキング:")
print(ranking[['学年', '名前', '総合点']])
パフォーマンスの最適化
大量データの並び替え
import numpy as np
# 大量データの作成(10万行)
large_df = pd.DataFrame({
'ID': range(100000),
'value': np.random.randn(100000),
'category': np.random.choice(['A', 'B', 'C'], 100000)
})
# 効率的な並び替え
import time
start_time = time.time()
sorted_df = large_df.sort_values(by=['category', 'value'])
end_time = time.time()
print(f"並び替え時間: {end_time - start_time:.2f}秒")
print(f"データ行数: {len(sorted_df):,}行")
メモリ効率の考慮
# inplace=True でメモリを節約
df_copy = df.copy()
df_copy.sort_values(by='売上', inplace=True)
print("inplace=Trueで並び替え:")
print(df_copy)
よくあるエラーと対処法

エラー1:列名が存在しない
try:
df.sort_values(by='存在しない列')
except KeyError as e:
print(f"エラー: {e}")
print("利用可能な列名:", df.columns.tolist())
エラー2:データ型の不一致
# 異なるデータ型が混在している場合
mixed_df = pd.DataFrame({
'data': [1, '2', 3.0, 'a', 5]
})
print("混在データ:")
print(mixed_df)
print("データ型:", mixed_df['data'].dtype)
# 数値のみを抽出して並び替え
numeric_only = pd.to_numeric(mixed_df['data'], errors='coerce')
mixed_df['numeric'] = numeric_only
sorted_mixed = mixed_df.sort_values(by='numeric')
print("\n数値のみ並び替え:")
print(sorted_mixed)
エラー3:欠損値の処理
# 欠損値を含むデータの安全な並び替え
df_with_na = df.copy()
df_with_na.loc[0, '売上'] = np.nan
# 欠損値を適切に処理
safe_sorted = df_with_na.sort_values(by='売上', na_position='last')
print("欠損値を考慮した並び替え:")
print(safe_sorted)
まとめ:sort_valuesで分析の”見える化”を!
sort_values()
を使いこなすことで、**「どの項目が多いのか・少ないのか」「どの傾向があるのか」**が一目で分かるようになります。この記事で学んだ内容をまとめると:
基本的な使い方
- 単一列の並び替え:
df.sort_values(by='列名')
- 昇順・降順の指定:
ascending=True/False
- 複数条件の並び替え:
by=['列1', '列2']
- インデックスの並び替え:
df.sort_index()
高度なテクニック
- 欠損値の処理:
na_position='first/last'
- カスタムソート:
key
パラメータの活用 - 条件付き並び替え:フィルタリングとの組み合わせ
- インデックスのリセット:
reset_index()
の使用
コメント