Menu

R の並べ替え: sort()、order()、arrange()

R の並べ替えの実際: ベクトルのための sort()、データフレームに order() のインデックスの技が必要な理由、降順と複数列の並べ替え、そして dplyr の arrange()。

このページのコードはエディタで実行できます - 編集してすぐに結果を確認できます。

sort() はベクトルの値を並べ替える

素のベクトルに対して、sort() はまさに期待どおりのことをします — 値を昇順で返します(元のベクトルは変わりません)。

知っておく価値のあるオプションが 2 つあります。decreasing = TRUE は向きを反転します。そして sort() は既定で NA を黙って 落としますsort(c(3, NA, 1))1 3 だけを返します。欠損値を並べ替え後も残す必要があるなら、行き先を指定しましょう: sort(x, na.last = TRUE) は並んだ値の後ろに配置して残します。

ここまでは当たり前です。面白いのは、なぜ sort() がデータフレームには 不適切な 道具なのか、という点です。

order() は位置を返す — 発想の転換

sort() は「順に並んだ値は何か?」に答えます。order() は別の問いに答えます。「順番に値を見ていくには どの位置 を訪ねればよいか?」

order(times) は指示書として読みます。最も小さい値は位置 2 にあり、次は位置 4、続いて 1、そして 3。その指示で添字付けすると — times[order(times)]sort(times) がそのまま再現されます。

なぜそれが重要なのでしょうか。データフレームの行は、一緒に動かなければならない値の チーム だからです。time の列だけを sort() で並べ替えると、1 つの列だけが並べ替わり、チームメイトが置き去りにされます — すべての行がぐちゃぐちゃになります。order() は代わりに行の位置を返し、その位置を括弧の行の枠に入れると 行全体 が動きます。

Ben の 9.8 は Ben の名前を伴って到着します。これがすべての種であり、base R でデータフレームを並べ替えるための 定番 の定型句です: df[order(df$column), ]。(表示される行ラベル 2 4 1 3 は、ついてきた元の行番号です。無害です。)

降順と複数列の並べ替え

数値の降順には列の符号を反転します — -time を昇順に並べることは time を降順に並べることです。また order() は複数の列を取り、先の列が優先され、後の列が同順位を解決します。

2 番目の呼び出しは部署をアルファベット順に並べ、各部署の 中で 給与を高い順に並べます。符号反転の技は数値にしか使えません — 文字列列に対する -df$name はエラーです。テキストの降順には代わりに order(df$name, decreasing = TRUE) を使いましょう(これはすべてのソートキーを一度に反転します)。

rank() は 3 番目の兄弟

ついでに触れると、rank(x) はさらに別の問い — 「各値は何位か?」 — に、何も動かさずに答えます。

sort() は順に並んだ値を、order() は訪ねるべき位置を、rank() は各値のその場での順位を返します。order()rank() は絶えず混同されます。両者が互いの逆置換であることに注目し、rank() は文字どおり順位が欲しいとき(ランキング表、パーセンタイル)にだけ使いましょう。

dplyr のやり方: arrange()

dplyr の arrange()order() の一連の手順を 1 つの動詞に包みます。列がソートキーで、desc() が 1 つを反転します(静的な例です。サンドボックスは base R しか実行しません)。

library(dplyr)

runners |> arrange(time)
staff   |> arrange(dept, desc(salary))

括弧も $ も符号反転の技も不要で、desc() は文字列列でも動きます。知っておく価値のある挙動の違いが 1 つあります。arrange() は向きに関係なく NA を末尾に置きます。一方 base の order() も既定では na.last = TRUE です。arrange()filter() などとどう連鎖するかは dplyr 入門 を参照してください。

文字列の並べ替えには鋭い刃がある

テキストを並べ替える際の注意が 2 つあります。第 1 に、テキストとして格納された数字は テキスト として並びます — 文字列の比較は記号ごとに進みます。

"10""2" より前に来るのは、比較が最初の記号で決着するからです: "1" < "2"。数値の列が奇妙に並ぶなら、ほぼ確実に文字列として格納されています — まず as.numeric() で変換しましょう(乱雑な CSV インポート の後によく起こることです)。

第 2 に、テキストの順序はシステムの ロケール に依存します — アクセント、大文字小文字、非ラテン文字は、あなたのノート PC と C ロケールのサーバーとで異なる並びになりえます。マシンをまたいで同一でなければならない並べ替え出力は、ロケールを明示的に設定するか、正規化したキーで並べ替えるべきです。

この記事のまとめ

  • sort(x) はベクトルの値を並べます。decreasing = TRUE で反転し、na.last = TRUE がなければ NA は落とされます。
  • order(x) は位置を返し、df[order(df$x), ] がデータフレームを並べ替えるための 定番 の base の定型句です。
  • 複数列は order(df$a, -df$b)。降順のための符号反転は数値にしか使えません。
  • rank() は並べ替えずに順位を返します — order() の代用にはなりません。
  • dplyr の arrange(dept, desc(salary)) は同じ並べ替えを少ない記号で書けます。
  • テキストでは "10""2" より前に来ます — 列の型を確認しましょう。

次は 行をグループ集計にまとめる方法 — table()tapply()aggregate()、そして dplyr の group_by() です。

よくある質問

R でデータフレームを列で並べ替えるにはどうすればよいですか?

行の括弧の中で order() を使います: df[order(df$price), ]order() は並べ替え後の行の位置を返し、それで添字付けするとデータフレーム全体が並べ替わります。ここで sort() は使えません — 1 つのベクトルの値を並べ替えるだけで、他の列とのつながりが失われます。

R の sort() と order() の違いは何ですか?

sort(x) は x の値を並べ替えて返します。order(x) は x を順序どおりに並べるための位置(インデックス)を返します。これは、ある列でデータフレーム全体を並べ替えるのに必要なものです: df[order(df$x), ]

R で降順に並べ替えるにはどうすればよいですか?

ベクトルなら sort(x, decreasing = TRUE)。データフレームなら df[order(-df$x), ](数値列の符号を反転)か、符号反転が使えない文字列列でも動く df[order(df$x, decreasing = TRUE), ] です。dplyr では arrange(df, desc(x)) です。

R で複数の列を使って並べ替えるにはどうすればよいですか?

すべてを order() に渡します: df[order(df$dept, -df$salary), ] は部署で並べ、各部署の中では給与の降順に並べます。先の引数が主キーで、後の引数が同順位を解決します。dplyr では arrange(df, dept, desc(salary)) です。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める