【Pandas入門】sort_values, sort_indexでDataFrameをソート!

こんにちは!インストラクターのフクロウです!listやnp.araryにはsort関数が用意されていましたね。これに対応するソート機能がPandasのDataFrameにも用意されています!

sort_values, sort_indexの2つのメソッドを駆使して、データフレームを自由自在にソートする方法をこの記事で勉強していきましょう!

目次

Pandasのデータをソートする2つのメソッド

pandasのDataFrameやSeriesなどをソートする主なメソッドは

  • sort_values:要素の値に沿ってソート」
  • sort_index:行や列の名前(インデックス)に沿ってソート


の2つです。それぞれがどんな使い方をするのかを見ていきましょう!

df.sort_values

DataFrameなどを要素の値に沿ってソートするメソッドです。いろいろ機能がついているので、入門者に知ってもらいたいメインの機能を掻い摘んで解説しますよ!!実際に使って試してみましょう!

データの準備

まずは解説に使うデータフレームを作りますよ!簡単に、iris datasetを読み込んでおきましょう。

In [1]:
import numpy as np 
import pandas as pd 
from sklearn.datasets import load_iris

In [2]:

iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df["label"] = [iris.target_names[i] for i in iris.target]

df.head(10)
Out[2]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 5.4 3.9 1.7 0.4 setosa
6 4.6 3.4 1.4 0.3 setosa
7 5.0 3.4 1.5 0.2 setosa
8 4.4 2.9 1.4 0.2 setosa
9 4.9 3.1 1.5 0.1 setosa

このままでもいいんですが、どうせならシャッフルしてソートしがいのあるデータフレームを用意しましょう!

In [3]:
df = df.sample(frac=1, random_state=0)

df.head(10)
Out[3]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
114 5.8 2.8 5.1 2.4 virginica
62 6.0 2.2 4.0 1.0 versicolor
33 5.5 4.2 1.4 0.2 setosa
107 7.3 2.9 6.3 1.8 virginica
7 5.0 3.4 1.5 0.2 setosa
100 6.3 3.3 6.0 2.5 virginica
40 5.0 3.5 1.3 0.3 setosa
86 6.7 3.1 4.7 1.5 versicolor
76 6.8 2.8 4.8 1.4 versicolor
71 6.1 2.8 4.0 1.3 versicolor

行のインデックスがぐちゃぐちゃになっていることがわかりますね。それではこれをsortしていきましょう。

基準になる列を指定してソート

df.sort_valuesでは、ソートの基準になる列の名前を指定する必要がありますよ!

In [4]:
sorted_df = df.sort_values("petal width (cm)") 

sorted_df.head(10)
Out[4]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
12 4.8 3.0 1.4 0.1 setosa
9 4.9 3.1 1.5 0.1 setosa
13 4.3 3.0 1.1 0.1 setosa
32 5.2 4.1 1.5 0.1 setosa
37 4.9 3.1 1.5 0.1 setosa
34 4.9 3.1 1.5 0.1 setosa
47 4.6 3.2 1.4 0.2 setosa
49 5.0 3.3 1.4 0.2 setosa
29 4.7 3.2 1.6 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa

ソート結果のデータフレームを見てみて下さい。petal width (cm)の列を順にソートしていることがわかります。ですが同じ0.1という値のデータが複数個あって、もっとソートの基準を増やしたくないですか?

そんなとき、df.sort_valuesではリストで列名を複数指定することで、ソートの基準を増やすことができます。

In [5]:
sorted_df = df.sort_values(["petal width (cm)", "petal length (cm)"]) 

sorted_df.head(10)
Out[5]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
13 4.3 3.0 1.1 0.1 setosa
12 4.8 3.0 1.4 0.1 setosa
37 4.9 3.1 1.5 0.1 setosa
34 4.9 3.1 1.5 0.1 setosa
32 5.2 4.1 1.5 0.1 setosa
9 4.9 3.1 1.5 0.1 setosa
22 4.6 3.6 1.0 0.2 setosa
35 5.0 3.2 1.2 0.2 setosa
14 5.8 4.0 1.2 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa

こうすることで、基本的にはpetal width (cm)列でソートして、同じ値のデータが出てきたときはpetal length (cm)の大小関係でソートすることができます。こうして条件を増やすことで、期待通りのソートができそうです!

ソート対象のオブジェクト自体を変更

さて、実はこのsort_values、もとのオブジェクト(ここだとdf)が変更されてないんですよ。

In [6]:
# 上でソートを適用したはずのdfを見てみよう 
df.head(10)
Out[6]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
114 5.8 2.8 5.1 2.4 virginica
62 6.0 2.2 4.0 1.0 versicolor
33 5.5 4.2 1.4 0.2 setosa
107 7.3 2.9 6.3 1.8 virginica
7 5.0 3.4 1.5 0.2 setosa
100 6.3 3.3 6.0 2.5 virginica
40 5.0 3.5 1.3 0.3 setosa
86 6.7 3.1 4.7 1.5 versicolor
76 6.8 2.8 4.8 1.4 versicolor
71 6.1 2.8 4.0 1.3 versicolor

前の章でソートしたsorted_dfの表と見比べてみてください。もとのオブジェクトであるdfはソートされていないことがわかります。

さて、もし元のオブジェクト(df)自体を変更したい場合、inplaceパラメータを使います。

In [7]:
df.sort_values(["petal width (cm)", "petal length (cm)"],
               inplace=True # Trueだと元の値を変更(指定しない場合はFalseになっている)
              )

df.head(10)
Out[7]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
13 4.3 3.0 1.1 0.1 setosa
12 4.8 3.0 1.4 0.1 setosa
37 4.9 3.1 1.5 0.1 setosa
34 4.9 3.1 1.5 0.1 setosa
32 5.2 4.1 1.5 0.1 setosa
9 4.9 3.1 1.5 0.1 setosa
22 4.6 3.6 1.0 0.2 setosa
35 5.0 3.2 1.2 0.2 setosa
14 5.8 4.0 1.2 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa

元のデータフレーム自体を変更することが簡単にできました。このような元のオブジェクト自体を変更する操作のことを破壊的変更といいます。

パラメータで指定しなければ普通は非破壊なので、ソートしたと思って元の配列を操作するようなことがないように注意したいですね。

昇順・降順

sort_valuesでは、指定しなければ昇順でソートしてくれます(これは他の多くのsort関数でも同じです)。これを逆に降順にしたい場合は、ascendingパラメータを使います。

※ascending

主な意味:のぼっていく、上昇的な

引用元:weblio https://ejje.weblio.jp/content/ascending

In [8]:
df.sort_values(["petal length (cm)"],
               inplace=True, # Trueだと元の値を変更(指定しない場合はFalseになっている)
               ascending=False # Trueだと昇順、Falseだと降順(指定しない場合はTrue)
              )

df.head(10)
Out[8]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
118 7.7 2.6 6.9 2.3 virginica
117 7.7 3.8 6.7 2.2 virginica
122 7.7 2.8 6.7 2.0 virginica
105 7.6 3.0 6.6 2.1 virginica
131 7.9 3.8 6.4 2.0 virginica
107 7.3 2.9 6.3 1.8 virginica
109 7.2 3.6 6.1 2.5 virginica
130 7.4 2.8 6.1 1.9 virginica
135 7.7 3.0 6.1 2.3 virginica
125 7.2 3.2 6.0 1.8 virginica

df.sort_index

DataFrameなどを行や列の名前(インデックス)に沿ってソートするメソッドです。

行の名前に従ってソート

何も指定しなければ、行の名前(ここだと0~149までのインデックスが割り振られています)に沿ってソートしてくれます。

In [9]:
sorted_df = df.sort_index()

sorted_df.head(10)
Out[9]:
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm) label
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
5 5.4 3.9 1.7 0.4 setosa
6 4.6 3.4 1.4 0.3 setosa
7 5.0 3.4 1.5 0.2 setosa
8 4.4 2.9 1.4 0.2 setosa
9 4.9 3.1 1.5 0.1 setosa

列の名前に従ってソート

行ができれば列でもできる!axis=1で列を列名のアルファベット順にソートしてくれます。

In [10]:
df.sort_index(axis=1,      # axis=1で列をソート
              inplace=True # sort_valesのようにinplaceやascendingパラメータもあります。
             )

df.head(10)
Out[10]:
label petal length (cm) petal width (cm) sepal length (cm) sepal width (cm)
118 virginica 6.9 2.3 7.7 2.6
117 virginica 6.7 2.2 7.7 3.8
122 virginica 6.7 2.0 7.7 2.8
105 virginica 6.6 2.1 7.6 3.0
131 virginica 6.4 2.0 7.9 3.8
107 virginica 6.3 1.8 7.3 2.9
109 virginica 6.1 2.5 7.2 3.6
130 virginica 6.1 1.9 7.4 2.8
135 virginica 6.1 2.3 7.7 3.0
125 virginica 6.0 1.8 7.2 3.2

まとめ

この記事では、DataFrameをソートする2つのメソッド「df.sort_values, df.sort_index」を解説しました!エクセルのsortのような操作がpandasでも簡単に実現できました。

注意点としては、pandas.sort* のように関数で用意されているわけではなく、pandas.DataFrame.sort* のようにメソッドとして提供されているところです。使い方は案外簡単ですし、データの前処理に大活躍しそうですね!

この記事を書いた人

第一言語はPythonです。
皆さんRustやりましょう。

目次