4

Rで作業すると、以下と同様の構造のデータがあります(コードブロック1)。そして、次の特性を持つ新しい data.frame を作成しようとしています:

一意の ID_1 値ごとに、2 つの新しい列が必要です。1 つは (ID_1 と方向 ==1 を共有する ID_2) のリストを含み、もう 1 つの列は (ID_1 と方向を共有する ID_2s ==0) のリストを含みます。 )、(次のコード ブロック 2 を参照)

データセット ブロック 1 (初期):

ID_1    ID_2    Direction
100001  1           1
100001  11          1
100001  111         1
100001  1111        0
100001  11111       0
100001  111111      0
100002  2           1
100002  22          1
100002  222         0
100002  2222        0
100003  3           1
100003  33          1
100003  333         1
100003  3333        0
100003  33333       0
100003  333333      1
100004  4           1
100004  44          1

に変えた:

データセット ブロック 2 (目的の出力):

ID_1    ID_2_D1             ID_2_D0
100001  1,11,111            1111,11111,111111
100002  2,22                222,222
100003  3,33,333,333333     3333,33333
100004  4,44    

私はこれを行うコードを持っています (サブセットのサブセットのループを取る) が、これを何百万もの一意の "ID_1" で実行しているため、非常に時間がかかります (何時間もかかります!!)。

アドバイス - おそらく apply() または plyr() パッケージを使用して、これをより高速に実行できますか?


参照用のコード:

DF <- data.frame(ID_1=c(100001,100001,100001,100001,100001,100001,100002,100002,100002,100002,100003,100003,100003,100003,100003,100003,100004,100004)
                   ,ID_2=c(1,11,111,1111,11111,111111,2,22,222,2222,3,33,333,3333,33333,333333,4,44)
                   ,Direction=c(1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,1,1)
                   )

私の現在の(遅すぎる)コード:

  DF2 <- data.frame( ID_1=DF[!duplicated(DF$ID_1),][,1])

  for (i in 1:length(unique(DF2$ID_1))){
    DF2$ID_2_D1[i] <- list(subset(DF,ID_1==unique(DF2$ID_1)[i] & Direction==1)$ID_2)
    DF2$ID_2_D0[i] <- list(subset(DF,ID_1==unique(DF2$ID_1)[i] & Direction==0)$ID_2)        
  }
4

3 に答える 3

7

このような:

library(reshape2)
dcast(DF, ID_1 ~ Direction, value.var = "ID_2", list)
#     ID_1                   0                  1
# 1 100001 1111, 11111, 111111         1, 11, 111
# 2 100002           222, 2222              2, 22
# 3 100003         3333, 33333 3, 33, 333, 333333
# 4 100004                                  4, 44    
于 2013-03-09T01:22:00.483 に答える
4

@flodelの答えは、私が考えることができる最も簡単なものですが、ここでは and を使用したベースRのオプションaggregateですmergesubsetステップで「 」引数を使用してaggregate、「方向 == 0」と「方向 == 1」の場合の個別の列を取得します。

temp1 <- aggregate(ID_2 ~ ., DF, as.vector, subset = c(Direction == 0))
temp2 <- aggregate(ID_2 ~ ., DF, as.vector, subset = c(Direction == 1))
merge(temp1[-2], temp2[-2], by = "ID_1", all = TRUE, suffixes=c("_0", "_1"))
#     ID_1              ID_2_0             ID_2_1
# 1 100001 1111, 11111, 111111         1, 11, 111
# 2 100002           222, 2222              2, 22
# 3 100003         3333, 33333 3, 33, 333, 333333
# 4 100004                NULL              4, 44

関連するアプローチ(それがより高速かどうかは不明)はsplit、サブセットを作成し、結果のリストlapplyを上書きし、次のことを容易にするために使用することです。aggregateReducemerge

Reduce(function(x, y) 
  merge(x, y, by = "ID_1", all = TRUE, suffixes = c("_0", "_1")), 
       lapply(split(DF[1:2], DF$Direction), 
              function(x) aggregate(ID_2 ~ ID_1, x, as.vector)))

そしてもちろん、data.table*何百万もの一意の "ID_1"* を処理する必要があると述べたように、 を使用した 1 つのアプローチを検討することをお勧めします。この小さな例で速度が向上する可能性はほとんどありませんが、実際のデータを使用する必要があります。

library(data.table)
DT <- data.table(DF, key = "ID_1")
DT0 <- DT[Direction == 0, list(D0 = list(ID_2)), by = key(DT)]
DT1 <- DT[Direction == 1, list(D1 = list(ID_2)), by = key(DT)]
DT0[DT1]
#      ID_1                D0              D1
# 1: 100001 1111,11111,111111        1,11,111
# 2: 100002          222,2222            2,22
# 3: 100003        3333,33333 3,33,333,333333
# 4: 100004                              4,44

アップデート

R Public チャット ルームで @Arun が述べたように、これは単純化されたdata.tableアプローチであり、2 つの個別のオブジェクトを作成してそれらをマージする必要がありません。

DT[, list(list(D0 = ID_2[Direction==0]), list(D1 = ID_2[Direction == 1])), by=ID_1]
于 2013-03-09T03:33:18.257 に答える
3

ここで適用関数を確実に使用できます。必要があるかどうかはわかりません (つまり、 をサブセット化するだけでさらに高速化できます)。あなたが望むものを達成することができます:

# Direction = 1
d1 <- lapply( unique( DF$ID_1 ) , function(x){ subset( DF , ID_1== x & Direction == 1)$ID_2 } )
d1 <- sapply( d1 , function(x){ paste0( x , sep = "," , collapse = "" ) } )
# Direction = 0
d0 <- lapply( unique( DF$ID_1 ) , function(x){ subset( DF , ID_1== x & Direction == 0)$ID_2 } )
d0 <- sapply( d0 , function(x){ paste0( x , sep = "," , collapse = "" ) } )


# Results dataframe
resDF <- data.frame(ID_1 = unique(DF$ID_1), d1, d0)
resDF
              d1                 d0                  
[1,] "100001" "1,11,111,"        "1111,11111,111111,"
[2,] "100002" "2,22,"            "222,2222,"         
[3,] "100003" "3,33,333,333333," "3333,33333,"       
[4,] "100004" "4,44,"            "," 

この方法がどれくらい速いか、知りたいです。

于 2013-03-09T01:16:54.017 に答える