21

ROW_NUMBER()Oracle 、RANK()、またはDENSE_RANK()(「順序に応じて行に整数値を割り当てる」; http://www.orafaq.com/node/55を参照)のようなランク関数に相当する R は何ですか?

各機能の機能は、アドホックな方法で実現できる可能性があることに同意します。しかし、私の主な関心事はパフォーマンスです。メモリと速度のために、結合またはインデックス アクセスを使用しないことをお勧めします。

4

5 に答える 5

30

このdata.tableパッケージは、特にバージョン 1.8.1 以降では、SQL 用語でのパーティションの機能の多くを提供します。rank(x, ties.method = "min")in R は OracleRANK()に似ており、関数を模倣するために因子 (以下で説明) を使用する方法がありDENSE_RANK()ます。模倣する方法ROW_NUMBERは、最後まで明らかになるはずです。

以下に例を示します: data.tableR-Forge からの最新バージョンをロードします。

install.packages("data.table",
  repos= c("http://R-Forge.R-project.org", getOption("repos")))

library(data.table)

いくつかのサンプル データを作成します。

set.seed(10)

DT<-data.table(ID=seq_len(4*3),group=rep(1:4,each=3),value=rnorm(4*3),
  info=c(sample(c("a","b"),4*2,replace=TRUE),
  sample(c("c","d"),4,replace=TRUE)),key="ID")

> DT
    ID group       value info
 1:  1     1  0.01874617    a
 2:  2     1 -0.18425254    b
 3:  3     1 -1.37133055    b
 4:  4     2 -0.59916772    a
 5:  5     2  0.29454513    b
 6:  6     2  0.38979430    a
 7:  7     3 -1.20807618    b
 8:  8     3 -0.36367602    a
 9:  9     3 -1.62667268    c
10: 10     4 -0.25647839    d
11: 11     4  1.10177950    c
12: 12     4  0.75578151    d

内でID降順でそれぞれをランク付けします (降順を示すために の前にあることに注意してください)。valuegroup-value

> DT[,valRank:=rank(-value),by="group"]
    ID group       value info valRank
 1:  1     1  0.01874617    a       1
 2:  2     1 -0.18425254    b       2
 3:  3     1 -1.37133055    b       3
 4:  4     2 -0.59916772    a       3
 5:  5     2  0.29454513    b       2
 6:  6     2  0.38979430    a       1
 7:  7     3 -1.20807618    b       2
 8:  8     3 -0.36367602    a       1
 9:  9     3 -1.62667268    c       3
10: 10     4 -0.25647839    d       3
11: 11     4  1.10177950    c       1
12: 12     4  0.75578151    d       2

ランク付けされている値に同点がある場合DENSE_RANK()、値を係数に変換してから、基になる整数値を返すことができます。たとえば、(と比較して)内IDに基づいてそれぞれをランク付けします。infogroupinfoRankinfoRankDense

DT[,infoRank:=rank(info,ties.method="min"),by="group"]
DT[,infoRankDense:=as.integer(factor(info)),by="group"]

R> DT
    ID group       value info valRank infoRank infoRankDense
 1:  1     1  0.01874617    a       1        1             1
 2:  2     1 -0.18425254    b       2        2             2
 3:  3     1 -1.37133055    b       3        2             2
 4:  4     2 -0.59916772    a       3        1             1
 5:  5     2  0.29454513    b       2        3             2
 6:  6     2  0.38979430    a       1        1             1
 7:  7     3 -1.20807618    b       2        2             2
 8:  8     3 -0.36367602    a       1        1             1
 9:  9     3 -1.62667268    c       3        3             3
10: 10     4 -0.25647839    d       3        2             2
11: 11     4  1.10177950    c       1        1             1
12: 12     4  0.75578151    d       2        2             2

ps こんにちは、マシュー・ダウルです。


リードとラグ

LEAD と LAG を模倣するには、ここで提供される回答から始めます。グループ内の ID の順序に基づいてランク変数を作成します。これは、上記のような偽のデータでは必要ありませんが、ID がグループ内で順番に並べられていないと、処理が少し難しくなります。以下は、連続していない ID を持つ新しい偽のデータです。

set.seed(10)

DT<-data.table(ID=sample(seq_len(4*3)),group=rep(1:4,each=3),value=rnorm(4*3),
  info=c(sample(c("a","b"),4*2,replace=TRUE),
  sample(c("c","d"),4,replace=TRUE)),key="ID")

DT[,idRank:=rank(ID),by="group"]
setkey(DT,group, idRank)

> DT
    ID group       value info idRank
 1:  4     1 -0.36367602    b      1
 2:  5     1 -1.62667268    b      2
 3:  7     1 -1.20807618    b      3
 4:  1     2  1.10177950    a      1
 5:  2     2  0.75578151    a      2
 6: 12     2 -0.25647839    b      3
 7:  3     3  0.74139013    c      1
 8:  6     3  0.98744470    b      2
 9:  9     3 -0.23823356    a      3
10:  8     4 -0.19515038    c      1
11: 10     4  0.08934727    c      2
12: 11     4 -0.95494386    c      3

次に、前の 1 レコードの値を取得するには、groupidRank変数を使用して から減算1idRank、引数を使用しmulti = 'last'ます。上記のレコード 2 エントリから値を取得するには、 を減算し2ます。

DT[,prev:=DT[J(group,idRank-1), value, mult='last']]
DT[,prev2:=DT[J(group,idRank-2), value, mult='last']]

    ID group       value info idRank        prev      prev2
 1:  4     1 -0.36367602    b      1          NA         NA
 2:  5     1 -1.62667268    b      2 -0.36367602         NA
 3:  7     1 -1.20807618    b      3 -1.62667268 -0.3636760
 4:  1     2  1.10177950    a      1          NA         NA
 5:  2     2  0.75578151    a      2  1.10177950         NA
 6: 12     2 -0.25647839    b      3  0.75578151  1.1017795
 7:  3     3  0.74139013    c      1          NA         NA
 8:  6     3  0.98744470    b      2  0.74139013         NA
 9:  9     3 -0.23823356    a      3  0.98744470  0.7413901
10:  8     4 -0.19515038    c      1          NA         NA
11: 10     4  0.08934727    c      2 -0.19515038         NA
12: 11     4 -0.95494386    c      3  0.08934727 -0.1951504

LEAD の場合、idRank変数に適切なオフセットを追加し、次のように切り替えますmulti = 'first'

DT[,nex:=DT[J(group,idRank+1), value, mult='first']]
DT[,nex2:=DT[J(group,idRank+2), value, mult='first']]

    ID group       value info idRank        prev      prev2         nex       nex2
 1:  4     1 -0.36367602    b      1          NA         NA -1.62667268 -1.2080762
 2:  5     1 -1.62667268    b      2 -0.36367602         NA -1.20807618         NA
 3:  7     1 -1.20807618    b      3 -1.62667268 -0.3636760          NA         NA
 4:  1     2  1.10177950    a      1          NA         NA  0.75578151 -0.2564784
 5:  2     2  0.75578151    a      2  1.10177950         NA -0.25647839         NA
 6: 12     2 -0.25647839    b      3  0.75578151  1.1017795          NA         NA
 7:  3     3  0.74139013    c      1          NA         NA  0.98744470 -0.2382336
 8:  6     3  0.98744470    b      2  0.74139013         NA -0.23823356         NA
 9:  9     3 -0.23823356    a      3  0.98744470  0.7413901          NA         NA
10:  8     4 -0.19515038    c      1          NA         NA  0.08934727 -0.9549439
11: 10     4  0.08934727    c      2 -0.19515038         NA -0.95494386         NA
12: 11     4 -0.95494386    c      3  0.08934727 -0.1951504          NA         NA
于 2012-07-12T09:18:38.107 に答える
7

からdata.table v1.9.5+、機能frank()高速ランク用)が実装されました。簡単にプログラミングできるfrank()インタラクティブなシナリオで役立ちます。frankv()

で利用可能なすべての操作を実装しますbase::rank。さらに、利点は次のとおりです。

  • frank()原子ベクトルに加えて、 listdata.frames、およびdata.tablesで動作します。

  • 列ごとに、ランクを昇順または降順に計算するかどうかを指定できます。

  • denseの他のタイプに加えて、ランク タイプも実装しbaseます。

  • 文字列でも使用-して、降順でランク付けできます。

これは、@ BenBarnes ' (優れた) 投稿の同じdata.table を使用した上記のすべてのポイントの図です。DT

データ:

require(data.table)
set.seed(10)
sample_n <- function(x, n) sample(x, n, replace=TRUE)
DT <- data.table(
        ID = seq_len(4*3),
        group = rep(1:4,each=3),
        value = rnorm(4*3),
        info = c(sample_n(letters[1:2], 8), sample_n(letters[3:4], 4)))

単一の列:

  • 計算denseランク:

    DT[, rank := frank(value, ties.method="dense"), by=group]
    

minmaxrandomaverageおよびの他の方法も使用できますfirst

  • 降順:

    DT[, rank := frank(-value, ties.method="dense"), by=group]
    
  • を使用すると、次frankvのようになりfrankます。

    # increasing order
    frankv(DT, "value", ties.method="dense")
    
    # decreasing order
    frankv(DT, "value", order=-1L, ties.method="dense")
    

複数の列

Subset of Data.SDを表し、そのグループに対応するデータを含むを使用できます。の詳細については、data.table HTML ビネットの概要を参照してください。.SD

  • info, valueでグループ化しながら列でランク付けgroup:

    DT[, rank := frank(.SD,  info, value, ties.method="dense"), by=group]
    
  • -降順を指定するために使用します。

    DT[, rank := frank(.SD,  info, -value, ties.method="dense"), by=group]
    
  • -文字列で直接使用することもできます

    DT[, rank := frank(.SD, -info, -value, ties.method="dense"), by=group]
    

frankv同様に使用して、列をcols引数に指定し、引数を使用して列をランク付けする順序を指定できorderます。


比較する小さなベンチマークbase::rank:

set.seed(45L)
x = sample(1e4, 1e7, TRUE)
system.time(ans1 <- base::rank(x, ties.method="first"))
#    user  system elapsed 
#  22.200   0.255  22.536 
system.time(ans2 <- frank(x, ties.method="first"))
#    user  system elapsed 
#   0.745   0.014   0.762 
identical(ans1, ans2) # [1] TRUE
于 2015-01-25T20:20:55.753 に答える
3

私は次の人と同じくらいdata.tableが好きですが、必ずしも必要というわけではありません。data.tableは常に高速ですが、グループの数がかなり少ない場合は、適度に大きなデータセットの場合でも、 plyrは適切に機能します。

BenBarnesがsを使用して行ったことは、 plyrdata.tableを使用して同じようにコンパクトに実行できます(ただし、前に述べたように、多くの場合、おそらく遅くなります)。

library(plyr)                
ddply(DT,.(group),transform,valRank = rank(-value))
ddply(DT,.(group),transform,valRank = rank(info,ties.method = "min"),
                            valRankDense = as.integer(factor(info)))

また、追加のパッケージを1つもロードしなくても、次のようになります。

do.call(rbind,by(DT,DT$group,transform,valRank = rank(-value)))
do.call(rbind,by(DT,DT$group,transform,valRank = rank(info,ties.method = "min"),
                                        valRankDense = as.integer(factor(info))))

ただし、その最後のケースでは、構文上の優れた点のいくつかが失われます。

于 2012-07-13T03:31:20.427 に答える
-6

オラクルの分析関数に直接相当するものはないと思います。Plyr は分析機能の一部を実現できる可能性がありますが、すべてを直接実現できるわけではありません。R は各機能を個別に複製できると確信していますが、すべてを実行できる単一のパッケージはないと思います。

R で実行する必要がある特定の操作がある場合は、グーグル検索を行い、空になった場合は、StackOverflow で具体的な質問をしてください。

于 2012-07-12T08:14:10.953 に答える