2

Rにデータフレームのリストがあり、それぞれがランクを含む異なるファイルからロードされています。たとえば、ファイルには、さまざまなレースのさまざまなアスリートの最終順位を含めることができます。

同じ要素 (アスリート) が複数のデータフレーム (レース) に表示される場合がありますが、必ずしもすべての要素が含まれるデータフレームはありません。

アスリートを行、レースを列として、ランキングのマトリックスを設定したいと思います。特定のレースでアスリートのランキングがない場合は、0 と読む必要があります。

たとえば、私が持っている場合:

[[1]]
   name rank
1 Alice    1
2   Bob    2
3 Carla    3
4 Diego    4

[[2]]
   name rank
1 Alice    2
2 Carla    1
3  Eric    3
4 Frank    4
5  Gary    5

[[3]]
   name rank
1   Bob    5
2 Carla    4
3 Diego    3
4  Eric    1
5  Gary    2

マトリックスを生成したい:

      1 2 3
Alice 1 2 0
Bob   2 0 5
Carla 3 1 4
Diego 4 0 3
Eric  0 3 1
Frank 0 4 0
Gary  0 5 2

これを行う効率的な方法を探しています:私のデータは200のデータフレームとデータフレームごとに10000のランク付けされた要素(合計で15000の一意の要素)に似ているため、最終的なマトリックスは約15000x200になります

4

4 に答える 4

2

より簡単なreshape2解決策は次のとおりです。

library(reshape2)

dcast(melt(ll, id.vars = 'name'), name ~ L1, fill = 0)
#   name 1 2 3
#1 Alice 1 2 0
#2   Bob 2 0 5
#3 Carla 3 1 4
#4 Diego 4 0 3
#5  Eric 0 3 1
#6 Frank 0 4 0
#7  Gary 0 5 2

Arun のベンチマークは非常に興味深いものdata.tableでした。実際にうまく機能するのは融解部分であり、reshape2実際にうまく機能するdcastのは です。そのため、両方の長所を以下に示します。

library(reshape2)
library(data.table)

pp = rbindlist(ll)[, id := rep(seq_along(ll), sapply(ll, nrow))]
dcast(pp, name ~ id, fill = 0, value.var = 'rank')

Arun のベンチマーク データの使用:

names <- tapply(sample(letters, 1e4, replace=TRUE), rep(1:(1e4/5), each=5), paste, collapse="")
names <- unique(names)

dd_create <- function() {
    nrow <- sample(c(100:500), 1)
    ncol <- 3
    data.frame(name = sample(names, nrow, replace=FALSE), rank = sample(nrow))
}

ll <- replicate(1e3, dd_create(), simplify = FALSE)

Arun_data.table <- function(ll) {
    pp <- rbindlist(ll)[, id := rep(seq_along(ll), sapply(ll, nrow))]
    setkey(pp, "name", "id")
    pp[CJ(unique(name), 1:1000)][is.na(rank), rank := 0L][, as.list(rank), by = name]
}

mix_of_both = function(ll) {
    pp = rbindlist(ll)[, id := rep(seq_along(ll), sapply(ll, nrow))]
    dcast(pp, name ~ id, fill = 0, value.var = 'rank')
}

require(microbenchmark)
microbenchmark(Arun_data.table(ll), mix_of_both(ll), times = 10)
# Unit: milliseconds
#                expr      min        lq    median        uq       max neval
# Arun_data.table(ll) 2568.333 2586.0079 2626.7704 2832.8076 2911.1314    10
#     mix_of_both(ll)  615.166  739.9383  766.8994  788.5822  821.0478    10
于 2013-06-18T18:43:39.150 に答える
1

別のReduceユースケースのようです。

merge.all <- function(x, y)
merge(x, y, all=TRUE, by="name")

# to avoid problems with merged name clashes
for(i in seq_along(ll))
    names(ll[[i]])[2] <- paste0("rank", i)

out <- Reduce(merge.all, ll)

merge名前の競合について不満を言うのを避けるために、データ フレームを少し変更する必要があります。ループは、forこの目的のために何でも同様に機能します。

欠落しているレースには NA があります。out[is.na(out)] <- 0;で 0 に置き換えることができます。ただし、これが賢明かどうかを自問する必要があります。たとえば、これを行うと、平均、分散などの単純な要約統計では誤解を招く結果が得られます。さらに複雑なモデリングを行う場合も同様です。対照的に、ほとんどの R モデリング関数は、NA を除外するのに十分スマートです。

于 2013-06-18T17:17:02.853 に答える