言語処理100本ノック第2章 Appendix. 厳格でないソートが行われる可能性についての検証

こんにちは。福田直起です。

この記事は、言語処理100本ノック2020の「第2章 : UNIXコマンド」Q17~Q19を解いていて見つけた、UbuntusortコマンドとPandasのsort_values()の厳格でない挙動について検証したものです。

解答・解説の前に

この記事の

  • 主な対象者と目的
  • 実行環境
  • 解答・解説を読む際の注意

は、以前の記事で説明しています。
検索サイトから直接このページにきたなどで、これらの内容をご存知ない方は、先に読んでいただくとこの記事の内容がよりわかりやすくなると思います。

Appendix-1 : sortコマンドのUbuntuにおける厳格でない挙動について

sort -rnk 3,3
と指定すると、3列目のみを参照して並び替えるのが正しい挙動ですが、今回の実行環境であるUbuntu 20.04.4 LTSでは、3列目から最後の列、1列目から2列目の順ですべての列を参照して並び替えるという挙動になりました。

以下にその検証を載せておきます。

検証用ファイル:sample.csv

A,1,1
Z,2,10
X,2,5
A,7,12
A,4,100
A,7,10
A,7,11

検証

$ cat sample.csv | sort -k2n -t,
A,1,1
X,2,5
Z,2,10
A,7,10
A,7,11
A,7,12
A,4,100
  
$ cat sample.csv | sort -k2n,2n -t,
A,1,1
X,2,5
Z,2,10
A,4,100
A,7,10
A,7,11
A,7,12

cat sample.csv | sort -k2n,2n -t,では上三行が

A,1,1
Z,2,10
X,2,5

となるのが本来正しい挙動ですが、ここでは3列目を参照してしまっているのかcat sample.csv | sort -k2n -t,と結果が一致してしまっています。

Appendix-2 : pandasのsort_values()の厳格でない挙動について

pandas1.4.3のsort_values()は、厳格でない挙動をすることがあります。
以下にその検証結果を残しておきます。

検証用ファイル:sample2.csv

William M 42422 1916
William M 42423 1916
William M 42424 1916
William M 42422 1917
William M 42423 1917
William M 42424 1917
William M 42422 1938
William M 42423 1938
William M 42424 1938
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000

検証用Pythonコード

import pandas as pd
  
data = pd.read_table('./sample2.csv', header=None, sep='\t',
                     names=['name', 'sex', 'number', 'year'])
  
sorted_lines = data.sort_values('number')
  
sorted_lines.to_csv('sample2_output-1.csv', sep='\t', header=False, index=False)

検証用Pythonコードの出力ファイル:sample2-output.csv

William M 42422 1916
William M 42422 1917
William M 42422 1938
William M 42423 1916
William M 42423 1938
William M 42423 1917
William M 42424 1938
William M 42424 1916
William M 42424 1917
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000
John    M 50000 2000

並び替えの対象に3番目の列であるnumberしか指定していないので、3列目が同じ値のときは4列目が1916→1917→1938の順で並ぶはずですが、そうなっていません。

ただ、検証の結果わかったのですが、どうやらデータが16行以下だとこの現象は発生しないようです。
sample2.csvは17行なので、どれか一行を削ると発生しないということです。

おわりに

以上、UbuntusortコマンドとPandasのsort_values()の厳格でない挙動について検証しました。

これらの挙動を検証するきっかけになった問題は、こちらのページで解答しています。 他の問題の回答は、まとめページにリンクを貼ってあります。

また、ブレインズコンサルティングでは一緒に働いてくれる仲間を募集しています。 ご興味のある方は、ぜひ一度採用サイトをご覧ください。