Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonのソート徹底解説:sorted()、list.sort()、np.argsort()、np.lexsort()の違いと使い方

データ要素を特定の順序で並べ替える処理は、プログラミングにおいて非常によく使われる操作です。Pythonでは配列(リスト)の要素をソートするために、sorted()関数とlist.sort()メソッドという2つの方法が用意されています。さらに、より高度なソートが必要な場合はNumPyライブラリのargsort()lexsort()が活躍します。

本記事では、それぞれの使い方と動作の違いを具体例とともにわかりやすく解説します。

sorted():元の配列を変更せずにソート

sorted()関数は、元の配列を変更することなく、ソート済みの新しい配列を返します。

a = [9,5,3,1,12,6]
b = sorted([9,5,3,1,12,6])
print "Sorted Array :\n",
print (b)
print "Original Array :\n",
print (a)

上記のコードを実行すると、次の結果が得られます。

Sorted Array :
[1, 3, 5, 6, 9, 12]
Original Array :
[9, 5, 3, 1, 12, 6]

出力を見ると、変数bには昇順に並び替えられた新しいリストが格納され、元のリストaはそのまま維持されていることがわかります。

list.sort():元の配列を直接書き換えるインプレースソート

sort()メソッドは、指定した配列自体を直接書き換える「インプレース(in-place)」方式でソートを行います。つまり、元の配列が変更される点に注意が必要です。

a = [9,5,3,1,12,6]
print "Original Array :\n",
print (a)
print "Sorted Array :\n",
a.sort()
print (a)

上記のコードを実行すると、次の結果が得られます。

Original Array :
[9, 5, 3, 1, 12, 6]
Sorted Array :
[1, 3, 5, 6, 9, 12]

このように、sort()は元の配列aそのものがソート済みの状態に置き換わります。

パフォーマンス面の注意:sorted()は元の配列のコピーを作成してからソートを行うため、コピー不要のsort()に比べてやや低速になります。用途に応じて使い分けましょう。

NumPyを使った高度なソート

より複雑なソート要件に対応するには、NumPyが便利です。NumPyは科学技術計算向けのデータ処理で広く利用されているPythonライブラリで、多彩な高度な機能を提供しています。以下では、純粋なPythonによるソート方法とNumPyによるソート方法の両方を見ていきます。

numpy.argsort():ソート後の「インデックス」を取得

NumPyのargsort()関数は、ソート済みの配列そのものではなく、ソート後の要素のインデックス(位置)を返します。以下の例では、まず配列の各要素とそのインデックスを表示し、その後にargsort()を適用して、ソートされた結果に対応するインデックスの配列を取得します。

import numpy as np
x = np.array([9,5,3,1,12,6])
print(x)

#Print the positions of elements
for i in range(len(x)):
print "[",i,"]",x[i],
print "\n"
# Print the indices of sorted elements
s = np.argsort(x)
print(s)

上記のコードを実行すると、次の結果が得られます。

[ 9 5 3 1 12 6]

[ 0 ] 9 [ 1 ] 5 [ 2 ] 3 [ 3 ] 1 [ 4 ] 12 [ 5 ] 6

[3 2 1 5 0 4]

結果の[3 2 1 5 0 4]は、「最小値の1はインデックス3、次は3がインデックス2…」というように、値を昇順に取り出すためのインデックス順を示しています。

numpy.lexsort():複数のキーによる多重ソート

lexsort()関数は、複数の配列を組み合わせた複数のソートキーによるソートに使用します。たとえば、まずA列でデータをソートし、同じ値の場合はB列の値で順序を決める、といった処理が可能です。

以下の例では、A列とB列を表す2つの配列を用意します。lexsort()を適用して「まずcolA、次にcolB」の優先順位でソートすると、結果としてcolAの要素のインデックスからなる配列が得られます。

import numpy as np
colA = [2,5,1,8,1] # First column
colB = [9,0,3,2,0] # Second column
# Sort by ColA and then by colB
sorted_index = np.lexsort((colB,colA))
print(sorted_index)
#print the result showing the
#column values as pairs
print [(colA[i],colB[i]) for i in sorted_index]

上記のコードを実行すると、次の結果が得られます。

[4 2 0 1 3]
[(1, 0), (1, 3), (2, 9), (5, 0), (8, 2)]

結果の見方を確認しましょう。colAの最小値である「1」は、インデックス2と4の2か所に存在します。しかし、出力ではインデックス4が先、2が後になっています。これは、colAの値が同じ場合にcolBの値も考慮されるためです。インデックス4のcolBは0、インデックス2のcolBは3であり、0の方が小さいため、(1, 0)が先に来るのです。このようにlexsort()は、最後のキーを最優先でソートする仕様になっている点にも注目してください。

まとめ

  • sorted():新しいソート済みリストを返す。元のリストは変更されないが、コピー分だけやや遅い。
  • list.sort():元のリストを直接書き換える高速なインプレースソート。
  • np.argsort():ソート後の値ではなく、そのインデックスを返す。
  • np.lexsort():複数のキーを使った多重ソートが可能。

用途に応じてこれらの関数を使い分けることで、Pythonでのデータ並べ替えを効率的に行えます。

  1. Pythonで挿入ソート(Insertion Sort)を実装する方法:アルゴリズムとサンプルコードを徹底解説

    この記事では、Python 3.x(およびそれ以前のバージョン)における挿入ソートの実装方法について詳しく解説します。挿入ソートは、トランプの手札を整理するイメージに近い、直感的で理解しやすいソートアルゴリズムです。挿入ソートのアルゴリズム挿入ソートは以下の手順で動作します。入力要素を順番に走査し、各反復ごとにソート済みの配列部分を少しずつ拡張していきます。現在注目している要素(キー)を、ソート済み部分の中で最も大きい値と比較します。キーがその値より大きければ、要素は元の位置のまま次の要素へ進みます。そうでなければ、ソート済み配列内の正しい位置を探し出し、そこへ移動させます。具体的には、ソート

  2. Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法

    この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要