2017-11-14 11 views
0

私はこの方法で変換する必要がある大きなdata.table(+ 12M行)を持っています:
各行を同じ最初の列の値(BookIdと呼ぶ)を1行に縮小し、他の列を大きな「データ」フィールドにマージします。 このテーブルには、2.7MユニークBookIdのforeachループで名前付き変数をエクスポートする

すなわち含まれています

 
BookId Col1  Col2  ...  ColN 
B001  Author Bob  ...  ... 
B002  Author Marc  ...  ... 
B002  Editor Bob Inc ...  ... 
B001  Editor MyBooks ...  ... 

Expeted結果:

BookId data 
B001  Bob,MyBooks, ... 
B002  Marc,Bob Inc, ... 

は今のところ、私はサブセットを使用してこの構造を再現することができましたが、これは実際にあります遅い場合は、行を構築するために最大300msかかるため、プロセスを達成するまでに最大9日かかります。

私はプロセスを高速化するために並列foreachループを使用することに決めました。
私の最初のapprochはbookId Listをループしていましたが、グローバルな全体的な時間を満足できないコアの数だけ分けることになりました(8コアは+1日を意味します)。また、各プロセスは大量のデータを自動エクスポートするため、すべてのdata.tableオブジェクトが必要です。

bookIdリストに基づいてプライマリdata.tableを独立したサブセットに分割し、各サブセットで各クラスタが動作するようにプロセスを改善する別のアプローチが見つかりました。 残念ながら、私はサブセットを "ダイナミック"な名前のクラスターにエクスポートできません。 ".export" paramを試しましたが、評価すると現在の "i"値を認識していないと思います。 これをどうすれば実現できますか?それも可能ですか?

私はRに新しいです、私は同じことを達成するための方法が常にたくさんあると言われました。これを達成するための最良の方法を選択しましたか?ここで

は私のコードです:ここでは

# Create cluster based on available cores 
cores = detectCores() 
cl <- makeCluster(cores) 
registerDoParallel(cl) 

# Load datas and generate BookId lists 
books <- fread("books.tab") 
bookId.unique.list <- unique(books$BookId) 
bookId.list <- books$BookId 

# Split datatable into "equals" subsets 
subset.length = ceiling(length(book.unique.list)/cores) 
for (i in 1:(cores)) { 
    start = (i-1)*subset.length 
    end = (i)*subset.length 
    list = book.unique.list[start:end] 
    assign(paste("books",i,sep=""), books[books$BookId %in% list]) 
    assign(paste("book.list",i,sep=""), list) 
} 

# Prepare resulting DT 
res = data.table(BookId = character(0), data = character(0)) 

# Parallel loop 
res <- foreach(i = 1:cores, .combine = rbind, .export = paste0("book", i), .packages = c("data.table")) %dopar% { 

    #Try to get the named subset corresponding to the current iteration (i) 
    # IE : Books1, Books2... 
    BookSubset = get(paste0("book", i)) 
    Book.list.subset = unique(BookSubset$BookId) 

    temp = data.table(BookId = character(0), data = character(0)) 

    for (i in 1:length(Book.list.subset)) { 
     bookId = Book.list.subset[i] 

     subset <- BookSubset[which(Book.list.subset ==bookId)] 
     output = capture.output(write.table(subset, stdout()quote=FALSE, row.names=FALSE,col.names=FALSE) 

     temp <- rbind(hist, data.table(zkf_BOOK = c(bookId), data = c(output))) 
    } 
    temp 
} 

dput[head(books))の結果である:ここで

structure(list(BookId = c("BOOKXXXX774051532082", "BOOKXXXX776514515608", 
    "BOOKXXXX776287821289", "BOOKXXXX776514515608", "BOOKXXXX774051532082", 
    "BOOKXXXX774051532082"), V2 = c("ZUSRXXXX8429", 
    "ZUSRXXXX371255229634", 
    "ZUSRXXXX656080986411", "ZUSRXXXX371255229634", "ZUSRXXXX8429", 
    "ZUSRXXXX8429"), V3 = c("BOOKEVTX776757835463", 
    "BOOKEVTX776762775464", 
    "BOOKEVTX776772854465", "BOOKEVTX776773643466", "", "BOOKEVTX776995487467" 
    ), V4 = c("ZACTIONX215229995154", "ZACTIONX533300043134", 
    "ZACTIONX533300043134", 
    "ZACTIONX533300043134", "", "ZACTIONX215229995154"), V5 = c("", 
    "", "", "", "", ""), V6 = c("", "", "", "", "MAILOUTX776774376684", 
    ""), V7 = c("", "", "", "", "", ""), V8 = c("", "", "", "", "", 
    ""), V9 = c("", "", "", "", "", ""), V10 = c("", "", "", "", 
    "", ""), V11 = c("", "", "", "", "", "")), .Names = c("zkf_BOOK", 
    "V2", "V3", "V4", "V5", "V6", "V7", "V8", "V9", "V10", "V11"), class = 
    c("data.table", 
    "data.frame"), row.names = c(NA, -6L)) 

は私の "本当の" データ入力のサンプルです:

BOOKXXXX774051532082 ZUSRXXXX8429BOOKEVTX776757835463 ZACTIONX215229995154        
BOOKXXXX776514515608 ZUSRXXXX371255229634 BOOKEVTX776762775464 ZACTIONX533300043134        
BOOKXXXX776287821289 ZUSRXXXX656080986411 BOOKEVTX776772854465 ZACTIONX533300043134        
BOOKXXXX776514515608 ZUSRXXXX371255229634 BOOKEVTX776773643466 ZACTIONX533300043134        
BOOKXXXX774051532082 ZUSRXXXX8429MAILOUTX776774376684      
BOOKXXXX774051532082 ZUSRXXXX8429BOOKEVTX776995487467 ZACTIONX215229995154        
BOOKXXXX776287821289 ZUSRXXXX656080986411 BOOKEVTX777107387468 ZACTIONX533300043134  

と期待される出力

BOOKXXXX774051532082 ZUSRXXXX8429|BOOKEVTX776757835463|ZACTIONX215229995154|||||||;ZUSRXXXX8429||||MAILOUTX776774376684|||||;ZUSRXXXX8429|BOOKEVTX776995487467|ZACTIONX215229995154||||||| 
BOOKXXXX776514515608 ZUSRXXXX371255229634|BOOKEVTX776762775464|ZACTIONX533300043134|||||||;ZUSRXXXX371255229634|BOOKEVTX776773643466|ZACTIONX533300043134||||||| 
BOOKXXXX776287821289 ZUSRXXXX656080986411|BOOKEVTX776772854465|ZACTIONX533300043134|||||||;ZUSRXXXX656080986411|BOOKEVTX777107387468|ZACTIONX533300043134||||||| 
+0

あなたはあなたの頭に書いてもらえますか? –

+3

正確な再現可能な入力と完全な対応出力を提供してください。あなたの問題に対する解決策は並列化ではなく、より効率的なRコードを書くことです。 – Roland

+0

@Airmoi、そのコメントはコメントではなく投稿に追加してください。 "編集"ボタンを使用 –

答えて

1

OPは、二つの折りたたみ操作を要求した:各列について

  1. |によって分離された一つのデータフィールド内(idカラムzkf_BOOK除く)すべての列を折りたたみます。各zkf_BOOK群について
  2. 、崩壊行は、行を横切っ崩壊 paste()を使用してのGroupWiseを行っている間 Reduce()にコールすることによって行われる列内崩壊 ;

によって分離します。 data.tableでは、by =パラメータの列は.SDの操作に含まれません。

library(data.table) 
setDT(books)[, paste(Reduce(function(x, y) paste(x, y, sep = "|"), .SD), collapse = ";"), 
      by = zkf_BOOK] 
   zkf_BOOK 
1: BOOKXXXX774051532082 
2: BOOKXXXX776514515608 
3: BOOKXXXX776287821289 
                                                   V1 
1: ZUSRXXXX8429|BOOKEVTX776757835463|ZACTIONX215229995154|||||||;ZUSRXXXX8429||||MAILOUTX776774376684|||||;ZUSRXXXX8429|BOOKEVTX776995487467|ZACTIONX215229995154||||||| 
2:             ZUSRXXXX371255229634|BOOKEVTX776762775464|ZACTIONX533300043134|||||||;ZUSRXXXX371255229634|BOOKEVTX776773643466|ZACTIONX533300043134||||||| 
3:                               ZUSRXXXX656080986411|BOOKEVTX776772854465|ZACTIONX533300043134||||||| 

印刷データの入力及び期待される出力は、7行(または複数)に基づいている間に予想される結果に不一致が原因dput[head(books))にのみ6行を返すことに注意してください。

+0

素晴らしい...私はそれほどスマートな解決策から遠かった... – Airmoi

関連する問題