複数の列でデータフレームを並べ替える方法


1316

data.frameを複数の列で並べ替えたい。たとえば、以下のdata.frameでは、列z(降順)で並べ替え、次に列b(昇順)で並べ替えます。

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
dd
    b x y z
1  Hi A 8 1
2 Med D 3 1
3  Hi A 9 1
4 Low C 9 2

回答:


1626

order()アドオンツールを使用せずに関数を直接使用できます。example(order)コードの先頭からトリックを使用するこの簡単な回答を参照してください。

R> dd[with(dd, order(-z, b)), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

2年以上後の編集: 列のインデックスでこれを行う方法を尋ねられました。答えは、目的のソート列をorder()関数に渡すだけです。

R> dd[order(-dd[,4], dd[,1]), ]
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1
R> 

列の名前を使用するのではなく(with()簡単に/直接アクセスするため)。


@Dirk Eddelbuettelは、行列に対して同様に簡単な方法はありますか?
ジョタ

14
同じように動作するはずですが、は使用できませんwithM <- matrix(c(1,2,2,2,3,6,4,5), 4, 2, byrow=FALSE, dimnames=list(NULL, c("a","b")))行列を作成してからM、を使用M[order(M[,"a"],-M[,"b"]),]して2列に並べます。
Dirk Eddelbuettel 2012年

4
十分に簡単:dd[ order(-dd[,4], dd[,1]), ]、ただしwith名前ベースのサブセット化には使用できません。
Dirk Eddelbuettel、2012年

18
2番目の例の実行中に、「単項演算子への無効な引数」エラーが発生しました。
Nailgun 2013年

21
"単項演算子の無効な引数"エラーは、文字列でマイナスを使用すると発生します。xtfrmたとえば、列をでラップして解決しますdd[ order(-xtfrm(dd[,4]), dd[,1]), ]
リッチーコットン

477

あなたの選択

  • order から base
  • arrange から dplyr
  • setorderそしてsetordervからdata.table
  • arrange から plyr
  • sort から taRifx
  • orderBy から doBy
  • sortData から Deducer

ほとんどの場合、依存関係がないことが重要でない限り、dplyrまたはdata.tableソリューションを使用する必要がありますbase::order


私は最近CRANパッケージにsort.data.frameを追加し、ここで説明するようにクラス互換にしました: sort.data.frameのジェネリック/メソッドの一貫性を作成する最良の方法

したがって、data.frame ddを指定すると、次のようにソートできます。

dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(taRifx)
sort(dd, f= ~ -z + b )

この関数の元の作者の1人である場合は、私に連絡してください。パブリックドメインについての議論はこちら:http ://chat.stackoverflow.com/transcript/message/1094290#1094290


上記のスレッドでHadleyが指摘したように、arrange()関数from plyrを使用することもできます。

library(plyr)
arrange(dd,desc(z),b)

ベンチマーク:多くの競合があったため、新しいRセッションで各パッケージをロードしたことに注意してください。特に、doByパッケージをロードすると、sort「次のオブジェクトは「x(位置17)」からマスクされます:b、x、y、z」をsort.data.frame返し、Deducerパッケージをロードすると、Kevin WrightまたはtaRifxパッケージから上書きされます。

#Load each time
dd <- data.frame(b = factor(c("Hi", "Med", "Hi", "Low"), 
      levels = c("Low", "Med", "Hi"), ordered = TRUE),
      x = c("A", "D", "A", "C"), y = c(8, 3, 9, 9),
      z = c(1, 1, 1, 2))
library(microbenchmark)

# Reload R between benchmarks
microbenchmark(dd[with(dd, order(-z, b)), ] ,
    dd[order(-dd$z, dd$b),],
    times=1000
)

時間の中央値:

dd[with(dd, order(-z, b)), ] 778

dd[order(-dd$z, dd$b),] 788

library(taRifx)
microbenchmark(sort(dd, f= ~-z+b ),times=1000)

時間の中央値:1,567

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=1000)

時間の中央値:862

library(doBy)
microbenchmark(orderBy(~-z+b, data=dd),times=1000)

時間の中央値:1,694

doByがパッケージをロードするのに少し時間がかかることに注意してください。

library(Deducer)
microbenchmark(sortData(dd,c("z","b"),increasing= c(FALSE,TRUE)),times=1000)

Deducerを読み込めませんでした。JGRコンソールが必要です。

esort <- function(x, sortvar, ...) {
attach(x)
x <- x[with(x,order(sortvar,...)),]
return(x)
detach(x)
}

microbenchmark(esort(dd, -z, b),times=1000)

アタッチ/デタッチのため、マイクロベンチマークと互換性がないようです。


m <- microbenchmark(
  arrange(dd,desc(z),b),
  sort(dd, f= ~-z+b ),
  dd[with(dd, order(-z, b)), ] ,
  dd[order(-dd$z, dd$b),],
  times=1000
  )

uq <- function(x) { fivenum(x)[4]}  
lq <- function(x) { fivenum(x)[2]}

y_min <- 0 # min(by(m$time,m$expr,lq))
y_max <- max(by(m$time,m$expr,uq)) * 1.05

p <- ggplot(m,aes(x=expr,y=time)) + coord_cartesian(ylim = c( y_min , y_max )) 
p + stat_summary(fun.y=median,fun.ymin = lq, fun.ymax = uq, aes(fill=expr))

マイクロベンチマークプロット

(線は下位四分位数から上位四分位数まで伸び、ドットは中央値です)


これらの結果と単純さ対速度の比重を考えると、私arrangeplyrパッケージに同意する必要があります。構文は単純ですが、基本的なRコマンドと同じように複雑であり、複雑です。通常、華麗なハドリーウィッカムの作品。私の唯一の不満は、並べ替えオブジェクトがによって呼び出される標準のR命名法に違反していることsort(object)です。


3
上記のggplot2マイクロベンチマーク関数がとして利用可能になりましたtaRifx::autoplot.microbenchmark
アリB.フリードマン

@ AriB.Friedman y軸の間隔とは何ですか/スケールは何ですか?
naught101 2012

@ naught101 y軸は0から始まります。スケールはマイクロ秒でなければなりません。
アリB.フリードマン

2
@AME bは、サンプルでどのようにソートされるかを確認します。デフォルトでは昇順で並べ替えられるため、でラップしないでくださいdesc。両方で昇順:arrange(dd,z,b)。両方で降順:arrange(dd,desc(z),desc(b))
Ari B. Friedman

2
あたりとして?arrange:「#注意:plyr機能がrow.namesを保存しません」。これにより、優れたarrange()機能を維持したい場合は、次善の策となりrow.namesます。
landroni 14年

149

ダークの答えは素晴らしいです。また、data.framesとdata.tablesのインデックス付けに使用される構文の主な違いを示しています。

## The data.frame way
dd[with(dd, order(-z, b)), ]

## The data.table way: (7 fewer characters, but that's not the important bit)
dd[order(-z, b)]

2つの呼び出しの違いはわずかですが、重要な結果をもたらす可能性があります。特に、プロダクションコードを記述したり、研究の正確性に関心がある場合は、変数名の不要な繰り返しを避けるのが最善です。data.table これを行うのに役立ちます。

変数名を繰り返すと問題が発生する例を次に示します。

ダークの答えからコンテキストを変更してみましょう。これは、多くのオブジェクト名があり、長くて意味のある大きなプロジェクトの一部だとしましょう。代わりにddと呼ばれquarterlyreportます。あれは。。。になる :

quarterlyreport[with(quarterlyreport,order(-z,b)),]

いいよ。何も問題はありません。次に、上司から、前四半期のレポートをレポートに含めるように依頼されます。あなたはあなたのコードを通り抜けlastquarterlyreport、さまざまな場所にオブジェクトを追加し、どういうわけか(いったい一体どうやって?)あなたはこれで終わります:

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

それはあなたが意味したことではありませんが、あなたがそれを速くやったので、あなたはそれを発見しませんでした、そしてそれは同様のコードのページに抱かれています。Rが意図したとおりであるとRが考えているため、コードは失敗しません(警告もエラーもありません)。レポートを読んだ人が見つかるといいのですが、読まないかもしれません。プログラミング言語を頻繁に使用する場合、この状況はなじみの深いものになるでしょう。それはあなたが言う「タイプミス」でした。あなたが上司に言う「タイプミス」を修正します。

ではdata.table、このような細部について心配しています。したがって、変数名を2回入力することを避けるために簡単なことを行いました。非常にシンプルなもの。既にiの枠内ddで自動的に評価されます。まったく必要ありませんwith()

の代わりに

dd[with(dd, order(-z, b)), ]

それはただ

dd[order(-z, b)]

そして代わりに

quarterlyreport[with(lastquarterlyreport,order(-z,b)),]

それはただ

quarterlyreport[order(-z,b)]

それは非常に小さな違いですが、いつかあなたの首を救うだけかもしれません。この質問に対するさまざまな回答を比較検討するときは、変数名の繰り返しを数えるときの判断基準の1つとして検討してください。かなりの数の繰り返しがある回答もあれば、まったくない回答もあります。


9
+1これはすばらしい点であり、私を苛立たせているRの構文の詳細に行き着きます。1 subset()回の呼び出しで同じオブジェクトを繰り返し参照する必要がないようにするために使用することがあります。
Josh O'Brien

2
@ naught101 data.table FAQ 1.9はそれに答えますか?
Matt Dowle

5
setorderこのスレッドはすべてのorderタイプの複製を送信する場所なので、ここにも新しい関数を追加できると思います。
David Arenburg、2015年

125

ここには優れた答えがたくさんありますが、dplyrは私がすばやく簡単に覚えることができる唯一の構文を提供します(したがって、今では非常に頻繁に使用しています)。

library(dplyr)
# sort mtcars by mpg, ascending... use desc(mpg) for descending
arrange(mtcars, mpg)
# sort mtcars first by mpg, then by cyl, then by wt)
arrange(mtcars , mpg, cyl, wt)

OPの問題について:

arrange(dd, desc(z),  b)

    b x y z
1 Low C 9 2
2 Med D 3 1
3  Hi A 8 1
4  Hi A 9 1

2
私の列が因子またはタイプファクター(またはそのようなもの)であり、この因子列を降順で並べ替え、その後に整数列を昇順で並べ替えたい場合、受け入れられた回答が機能しません。しかし、これはうまくいきます!ありがとうございました!
Saheel Godhane 14

10
なぜ「だけ」なのか?data.tableはdd[order(-z, b)]かなり使いやすく覚えやすいと思います。
Matt Dowle、2014年

2
同意します。これらの2つの方法の間にはそれほど多くはなく、他の多くの点でもdata.table大きな貢献Rです。この場合、ブラケットのセットが1つ少なくなる(またはブラケットのタイプが1つ少なくなる)と、認識負荷がわずかに認識できる程度に減少するのではないかと思います。
Ben

7
私にとってそれarrange()は完全に宣言的であるという事実に帰着しますが、そうでdd[order(-z, b)]はありません。
Mullefa

83

Rパッケージdata.tableは、単純な構文でdata.tablesの高速かつメモリ効率の高い順序付けを提供します(Mattが彼の回答でかなりうまく強調しています)。setorder()それ以来、かなり多くの改善と新しい機能がありました。からv1.9.5+data.framessetorder()でも動作します

最初に、十分な大きさのデータセットを作成し、他の回答から言及されたさまざまなメソッドをベンチマークしてから、data.tableの機能をリストします

データ:

require(plyr)
require(doBy)
require(data.table)
require(dplyr)
require(taRifx)

set.seed(45L)
dat = data.frame(b = as.factor(sample(c("Hi", "Med", "Low"), 1e8, TRUE)),
                 x = sample(c("A", "D", "C"), 1e8, TRUE),
                 y = sample(100, 1e8, TRUE),
                 z = sample(5, 1e8, TRUE), 
                 stringsAsFactors = FALSE)

ベンチマーク:

報告されるタイミングは、system.time(...)以下に示すこれらの関数での実行からのものです。タイミングは以下のとおりです(最も遅いものから最も速いものの順に)。

orderBy( ~ -z + b, data = dat)     ## doBy
plyr::arrange(dat, desc(z), b)     ## plyr
arrange(dat, desc(z), b)           ## dplyr
sort(dat, f = ~ -z + b)            ## taRifx
dat[with(dat, order(-z, b)), ]     ## base R

# convert to data.table, by reference
setDT(dat)

dat[order(-z, b)]                  ## data.table, base R like syntax
setorder(dat, -z, b)               ## data.table, using setorder()
                                   ## setorder() now also works with data.frames 

# R-session memory usage (BEFORE) = ~2GB (size of 'dat')
# ------------------------------------------------------------
# Package      function    Time (s)  Peak memory   Memory used
# ------------------------------------------------------------
# doBy          orderBy      409.7        6.7 GB        4.7 GB
# taRifx           sort      400.8        6.7 GB        4.7 GB
# plyr          arrange      318.8        5.6 GB        3.6 GB 
# base R          order      299.0        5.6 GB        3.6 GB
# dplyr         arrange       62.7        4.2 GB        2.2 GB
# ------------------------------------------------------------
# data.table      order        6.2        4.2 GB        2.2 GB
# data.table   setorder        4.5        2.4 GB        0.4 GB
# ------------------------------------------------------------
  • data.tableDT[order(...)]構文は、他のメソッドの最速のメソッド()と比べて最大10倍高速でしたdplyrが、と同じ量のメモリを消費していdplyrます。

  • data.tableさんがsetorder()いた〜14倍速く他の方法(の最速よりもdplyr生かしつつ、)だけ0.4ギガバイト余分なメモリをdatこれで、必要な順序になりました(参照によって更新されるため)。

data.tableの機能:

速度:

  • data.tableは、基数の順序を実装しているため、非常に高速です。

  • 構文DT[order(...)]は内部的に最適化され、data.tableの高速な順序付けも使用します。使い慣れたベースR構文を使い続けることができますが、プロセスは高速化されます(メモリ使用量も少なくなります)。

メモリ:

  • ほとんどの場合、並べ替え後に元のdata.frameまたはdata.tableは必要ありません。つまり、通常は結果を同じオブジェクトに割り当てます。次に例を示します。

    DF <- DF[order(...)]

    問題は、元のオブジェクトのメモリの少なくとも2倍(2x)を必要とすることです。であることがメモリ効率の良いdata.tableしたがって、機能を提供しますsetorder()

    setorder()追加のコピーを作成せずにdata.tables by referenceインプレース)を並べ替えます。1つの列のサイズに等しい追加のメモリのみを使用します。

その他の機能:

  1. それはサポートしていますintegerlogicalnumericcharacterとさえbit64::integer64種類。

    なおfactorDatePOSIXctなど。クラスがすべてですinteger/ numericタイプは、追加の属性を下にし、したがって、うまくとしてサポートされています。

  2. ベースRでは-、文字列を使用してその列を降順で並べ替えることはできません。代わりにを使用する必要があります-xtfrm(.)

    ただし、data.tableでは、たとえば、dat[order(-x)]またはだけを実行できsetorder(dat, -x)ます。


data.tableに関する非常に有益な回答をありがとうございます。しかし、「ピークメモリ」とは何か、どのように計算したのかわかりません。説明していただけますか?ありがとうございました !
Julien Navarre 2015年

Instruments- >割り当てを使用し、「すべてのヒープと割り当てVM」のサイズを報告しました。
2015年

2
コメント内の@Arun Instrumentsリンクは無効です。アップデートを投稿しますか?
MichaelChirico

:@MichaelChiricoはここでアップル製の楽器についての情報へのリンクですdeveloper.apple.com/library/content/documentation/...
n1k31t4



39

があり、降順data.frame Aと呼ばれる列を使用してそれをソートするとしますx。並べ替えを呼び出すdata.frame newdata

newdata <- A[order(-A$x),]

昇順が必要な場合は"-"、何も入れ替えません。あなたは次のようなものを持つことができます

newdata <- A[order(-A$x, A$y, -A$z),]

どこxzで一部の列ですdata.frame A。つまりdata.frame Ax降順、y昇順、z降順で並べ替えます。


32

SQLが自然に生まれてくる場合、sqldfパッケージはORDER BYCoddが意図したように処理します。


7
MJM、このパッケージを指摘してくれてありがとう。それは信じられないほど柔軟性があり、私の作業の半分はすでにSQLデータベースから取得することで行われているため、直感的な構文よりもRの多くを学ぶよりも簡単です。
Brandon Bertelsen、2010

31

または、Deducerパッケージを使用する

library(Deducer)
dd<- sortData(dd,c("z","b"),increasing= c(FALSE,TRUE))

19

プログラムで並べ替える方法についてOPに追加されたコメントへの応答:

使用するdplyrと、data.table

library(dplyr)
library(data.table)

dplyr

ただ、使用のarrange_ための標準評価版です、arrange

df1 <- tbl_df(iris)
#using strings or formula
arrange_(df1, c('Petal.Length', 'Petal.Width'))
arrange_(df1, ~Petal.Length, ~Petal.Width)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.4         3.9          1.3         0.4  setosa
7           5.5         3.5          1.3         0.2  setosa
8           4.4         3.0          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...


#Or using a variable
sortBy <- c('Petal.Length', 'Petal.Width')
arrange_(df1, .dots = sortBy)
    Source: local data frame [150 x 5]

   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          (dbl)       (dbl)        (dbl)       (dbl)  (fctr)
1           4.6         3.6          1.0         0.2  setosa
2           4.3         3.0          1.1         0.1  setosa
3           5.8         4.0          1.2         0.2  setosa
4           5.0         3.2          1.2         0.2  setosa
5           4.7         3.2          1.3         0.2  setosa
6           5.5         3.5          1.3         0.2  setosa
7           4.4         3.0          1.3         0.2  setosa
8           4.4         3.2          1.3         0.2  setosa
9           5.0         3.5          1.3         0.3  setosa
10          4.5         2.3          1.3         0.3  setosa
..          ...         ...          ...         ...     ...

#Doing the same operation except sorting Petal.Length in descending order
sortByDesc <- c('desc(Petal.Length)', 'Petal.Width')
arrange_(df1, .dots = sortByDesc)

詳細はこちら:https : //cran.r-project.org/web/packages/dplyr/vignettes/nse.html

式を評価するための環境も取得するため、式を使用することをお勧めします

データ表

dt1 <- data.table(iris) #not really required, as you can work directly on your data.frame
sortBy <- c('Petal.Length', 'Petal.Width')
sortType <- c(-1, 1)
setorderv(dt1, sortBy, sortType)
dt1
     Sepal.Length Sepal.Width Petal.Length Petal.Width   Species
  1:          7.7         2.6          6.9         2.3 virginica
  2:          7.7         2.8          6.7         2.0 virginica
  3:          7.7         3.8          6.7         2.2 virginica
  4:          7.6         3.0          6.6         2.1 virginica
  5:          7.9         3.8          6.4         2.0 virginica
 ---                                                            
146:          5.4         3.9          1.3         0.4    setosa
147:          5.8         4.0          1.2         0.2    setosa
148:          5.0         3.2          1.2         0.2    setosa
149:          4.3         3.0          1.1         0.1    setosa
150:          4.6         3.6          1.0         0.2    setosa

18

orderは次の例で学び、それが長い間混乱しました。

set.seed(1234)

ID        = 1:10
Age       = round(rnorm(10, 50, 1))
diag      = c("Depression", "Bipolar")
Diagnosis = sample(diag, 10, replace=TRUE)

data = data.frame(ID, Age, Diagnosis)

databyAge = data[order(Age),]
databyAge

ので、この例では、働く唯一の理由はあるorderでソートされてvector Ageいないという列で、Agedata frame data

これを確認するには、read.tableわずかに異なる列名を使用し、上記のベクトルを使用せずに、同じデータフレームを作成します。

my.data <- read.table(text = '

  id age  diagnosis
   1  49 Depression
   2  50 Depression
   3  51 Depression
   4  48 Depression
   5  50 Depression
   6  51    Bipolar
   7  49    Bipolar
   8  49    Bipolar
   9  49    Bipolar
  10  49 Depression

', header = TRUE)

orderという名前のベクターがないため、上記のライン構造は機能しなくなりましたage

databyage = my.data[order(age),]

orderageでソートするため、次の行は機能しmy.dataます。

databyage = my.data[order(my.data$age),]

この例に長い間混乱していたので、これは投稿する価値があると思いました。この投稿がスレッドに適切であると思われない場合は、削除できます。

編集:2014年5月13日

以下は、列名を指定せずにすべての列でデータフレームを並べ替える一般的な方法です。以下のコードは、左から右または右から左に並べ替える方法を示しています。これは、すべての列が数値の場合に機能します。文字列を追加して試したことはありません。

1 do.callか月か2か月前に、別のサイトの古い投稿でコードを見つけました。私はその投稿を今すぐ再配置できるかどうかわかりません。現在のスレッドが注文するための最初のヒットでdata.frameでをR。そのため、元のdo.callコードの拡張バージョンが役立つと思いました。

set.seed(1234)

v1  <- c(0,0,0,0, 0,0,0,0, 1,1,1,1, 1,1,1,1)
v2  <- c(0,0,0,0, 1,1,1,1, 0,0,0,0, 1,1,1,1)
v3  <- c(0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1)
v4  <- c(0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1)

df.1 <- data.frame(v1, v2, v3, v4) 
df.1

rdf.1 <- df.1[sample(nrow(df.1), nrow(df.1), replace = FALSE),]
rdf.1

order.rdf.1 <- rdf.1[do.call(order, as.list(rdf.1)),]
order.rdf.1

order.rdf.2 <- rdf.1[do.call(order, rev(as.list(rdf.1))),]
order.rdf.2

rdf.3 <- data.frame(rdf.1$v2, rdf.1$v4, rdf.1$v3, rdf.1$v1) 
rdf.3

order.rdf.3 <- rdf.1[do.call(order, as.list(rdf.3)),]
order.rdf.3

4
data.frameではなくdata.tableにデータを格納する場合、その構文は機能します。require(data.table); my.dt <- data.table(my.data); my.dt[order(age)]これは、列名が[]括弧内で使用できるようになるため機能します。
Frank

私はdownvoteはここでは必要だとは思わないが、私は、これはに多くの追加だと思いませんかどちらも疑問そのうちのいくつかはすでにと要件キャプチャ、特に回答の既存のセットを考慮すると、手でdata.frameどちらかの使用に秒with$
A5C1D2H2I1M1N2O1R2T1 2014

1
これに賛成票を入れるとdo.call、複数列のデータフレームを並べ替える短時間の作業になります。単純do.call(sort, mydf.obj)に、美しいカスケードソートが行われます。
AdamO 2016年

17

ダークの答えは良いですが、並べ替えを維持する必要がある場合は、そのデータフレームの名前に並べ替えを適用する必要があります。コード例を使用:

dd <- dd[with(dd, order(-z, b)), ] 

13

dplyerのarrange()は私のお気に入りのオプションです。パイプオペレーターを使用して、最も重要でない側面から最も重要な側面へ

dd1 <- dd %>%
    arrange(z) %>%
    arrange(desc(x))

7

完全を期すために、列番号によるソートについてはあまり言及されていないので...(列の順序が変更されてエラーが発生する可能性があるため)望ましくないことはよくありますが、特定の状況(たとえば、迅速な作業が必要であり、列が順序を変更するリスクがない場合)では、特に多数の列を扱う場合に、これが最も賢明なことかもしれません。

その場合、do.call()救助に来る:

ind <- do.call(what = "order", args = iris[,c(5,1,2,3)])
iris[ind, ]

##        Sepal.Length Sepal.Width Petal.Length Petal.Width    Species
##    14           4.3         3.0          1.1         0.1     setosa
##    9            4.4         2.9          1.4         0.2     setosa
##    39           4.4         3.0          1.3         0.2     setosa
##    43           4.4         3.2          1.3         0.2     setosa
##    42           4.5         2.3          1.3         0.3     setosa
##    4            4.6         3.1          1.5         0.2     setosa
##    48           4.6         3.2          1.4         0.2     setosa
##    7            4.6         3.4          1.4         0.3     setosa
##    (...)

6

完全を期すためにsortByCol()BBmiscパッケージの関数を使用することもできます。

library(BBmisc)
sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE))
    b x y z
4 Low C 9 2
2 Med D 3 1
1  Hi A 8 1
3  Hi A 9 1

パフォーマンス比較:

library(microbenchmark)
microbenchmark(sortByCol(dd, c("z", "b"), asc = c(FALSE, TRUE)), times = 100000)
median 202.878

library(plyr)
microbenchmark(arrange(dd,desc(z),b),times=100000)
median 148.758

microbenchmark(dd[with(dd, order(-z, b)), ], times = 100000)
median 115.872

4
メソッドが最も遅いときにパフォーマンス比較を追加するのはおかしい...とにかく、4行でベンチマークを使用することの価値を疑わしいdata.frame
MichaelChirico

5

昔のメカニカルカードソーターと同じように、最初に重要度の低いキーで並べ替え、次に重要度の高いキーで並べ替えます。ライブラリは不要で、任意の数のキーと、昇順キーと降順キーの任意の組み合わせで機能します。

 dd <- dd[order(dd$b, decreasing = FALSE),]

これで、最も重要なキーを実行する準備が整いました。ソートは安定しており、最も重要なキーの関係はすでに解決されています。

dd <- dd[order(dd$z, decreasing = TRUE),]

これは最速ではないかもしれませんが、確かにシンプルで信頼性があります



4

列名が毎回異なる可能性があるn列の順序付けプロセスを自動化したいとき、私は上記の解決策に苦労していました。私はpsychパッケージからこれを簡単な方法で実行するための非常に役立つ関数を見つけました:

dfOrder(myDf, columnIndices)

どこcolumnIndicesあなたがそれらをソートする順番で、1つ以上の列のインデックスが、あります。詳細はこちら:

'psych'パッケージのdfOrder関数

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.