Ich habe eine große data.table (+ 12M Zeilen), die ich auf diese Weise konvertieren müssen:
Collapse jede Zeile mit der gleichen ersten Spalte Wert (nennen wir es BookId) in 1 Zeile und füge andere Spalten in ein großes "Daten" -Feld ein. Diese Tabelle enthält 2.7M einzigartige BookID desExport benannte Variable in foreach Schleife
Ie:
BookId Col1 Col2 ... ColN B001 Author Bob ... ... B002 Author Marc ... ... B002 Editor Bob Inc ... ... B001 Editor MyBooks ... ...
Expeted Ergebnis:
BookId data B001 Bob,MyBooks, ... B002 Marc,Bob Inc, ...
Vorerst habe ich in der Lage, diese Struktur zu reproduzieren Teilmengen verwenden, aber das ist wirklich Langsam dauert es bis zu 300ms, um eine Reihe zu bauen, was bedeutet, dass es bis zu 9 Tage dauern wird, um den Prozess zu erreichen.
Also entschied ich mich, eine parallele foreach-Schleife zu verwenden, um den Prozess zu beschleunigen.
Meine erste Annäherung war es, die bookId-Liste zu durchlaufen, aber es würde nur die globale Gesamtzeit durch die Anzahl der Kerne teilen, die nicht zufriedenstellend ist (8 Kerne bedeutet +1 Tag). Das bedeutet auch, dass jeder Prozess eine sehr große Datenmenge automatisch exportiert, da alle das gesamte data.table-Objekt benötigen.
Ich fand einen anderen Ansatz, um den Prozess zu verbessern, indem Sie die primäre data.table in unabhängige Subsets basierend auf bookId-Liste aufteilen und dann jeden Cluster an diesen Subsets arbeiten lassen (weniger Zeilen bedeuten schnellere Generierung von Subsets). Leider kann ich meine Untergruppen nicht in Cluster exportieren, da sie einen "dynamischen" Namen haben. Ich habe versucht ".export" param, aber ich denke, es ist nicht bewusst, den aktuellen "i" -Wert bei der Auswertung. Wie kann ich das erreichen? Ist es überhaupt möglich ?
Ich bin neu in R, mir wurde gesagt, dass es immer viele Möglichkeiten gibt, um das Gleiche zu erreichen, habe ich den besten Ansatz gewählt, um dies zu erreichen?
Hier ist mein Code:
# 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
}
Hier ist das Ergebnis von 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))
Hier ist ein Beispiel meiner "echte" Dateneingabe:
BOOKXXXX774051532082 ZUSRXXXX8429BOOKEVTX776757835463 ZACTIONX215229995154
BOOKXXXX776514515608 ZUSRXXXX371255229634 BOOKEVTX776762775464 ZACTIONX533300043134
BOOKXXXX776287821289 ZUSRXXXX656080986411 BOOKEVTX776772854465 ZACTIONX533300043134
BOOKXXXX776514515608 ZUSRXXXX371255229634 BOOKEVTX776773643466 ZACTIONX533300043134
BOOKXXXX774051532082 ZUSRXXXX8429MAILOUTX776774376684
BOOKXXXX774051532082 ZUSRXXXX8429BOOKEVTX776995487467 ZACTIONX215229995154
BOOKXXXX776287821289 ZUSRXXXX656080986411 BOOKEVTX777107387468 ZACTIONX533300043134
und die erwartete Ausgabe
BOOKXXXX774051532082 ZUSRXXXX8429|BOOKEVTX776757835463|ZACTIONX215229995154|||||||;ZUSRXXXX8429||||MAILOUTX776774376684|||||;ZUSRXXXX8429|BOOKEVTX776995487467|ZACTIONX215229995154|||||||
BOOKXXXX776514515608 ZUSRXXXX371255229634|BOOKEVTX776762775464|ZACTIONX533300043134|||||||;ZUSRXXXX371255229634|BOOKEVTX776773643466|ZACTIONX533300043134|||||||
BOOKXXXX776287821289 ZUSRXXXX656080986411|BOOKEVTX776772854465|ZACTIONX533300043134|||||||;ZUSRXXXX656080986411|BOOKEVTX777107387468|ZACTIONX533300043134|||||||
Können Sie 'dput (Kopf (Bücher))' –
Bitte geben Sie genaue reproduzierbare Eingabe und die volle entsprechende Ausgabe. Die Lösung für Ihr Problem ist nicht die Parallelisierung, sondern das Schreiben von effizienterem R-Code. – Roland
@Airmoi, bitte fügen Sie diese Ausgabe zu Ihrem Beitrag hinzu, nicht in den Kommentaren. Verwenden Sie die Schaltfläche "Bearbeiten" –