2016-10-30 9 views
0

Ich versuche, zwei verschachtelte for-Schleifen in zwei verschachtelte foreach-Schleifen zu konvertieren, um die Werte eines Datenrahmens basierend auf übereinstimmenden Voraussetzungen zu ändern. Grund dafür ist, glaube ich, dass ich den Prozess erheblich beschleunigen kann. Im Folgenden ist ein Beispiel für meine Code:Verschachtelte foreach-Schleife, die Werte in einem Datenrahmen ändert R

library(foreach) # for loop to parallelize 
library(doMC) # create the number of cores to use 

# set the number of cores to use 
registerDoMC(22) # number of CPU cores 

file_list <- c("a", "b", "c") 
ldf <- c(data.frame(Date = c("2016-10-01", "2016-10-02", "2016-10-03", "2016-10-04")), 
    data.frame(Date = c("2016-10-07", "2016-10-08", "2016-10-09")), 
    data.frame(Date = c("2016-10-15", "2016-10-16", "2016-10-17", "2016-10-18", "2016-10-19"))) 

DF <- data.frame(Date = seq(as.POSIXct("2016-10-01", tz = "UTC"), as.POSIXct("2016-10-31", tz = "UTC"), by = 'day'), 
      A = 0, 
      B = 0, 
      C = 0) 

DF2 <- DF # DF2 is used to compare my attempt result 


for (i in 1:length(file_list)) 
{ 
    Date <- ldf[[i]] 
    Date <- as.POSIXct(Date, tz = "UTC") 

    for (j in 1:length(Date)) 
    { 
    ROW <- which(DF$Date == Date[j]) 
    DF[ROW,i+1] <- 1 
    } 

} 

throwaway <- foreach (i = 1:length(file_list)) %dopar% 
{ 
    Date <- ldf[[i]] 
    Date <- as.POSIXct(Date, tz = "UTC") 

    foreach (j = 1:length(Date)) %do% 
    { 
    ROW <- which(DF2$Date == Date[j]) 
    DF2[ROW,i+1] <- 1 
    return(NULL) 
    } 
} 

filelist eine Liste der Dateien, die ich in

Lesen am

ldf wird die Variable verwendet, um die Dateien zu speichern, die

Diese beiden Variablen gelesen werden, sind in diesem Beispiel erfunden, nur um ein reproduzierbares Beispiel zu haben.

DF ist, wo ich die Änderungen in den Werten der foreach Schleifen

DF2 ist mein Versuch Versuch gemacht speichern werde und wo es gespeichert wird

Der Ausgang Ich stehe auf, dass von DF , aber DF2 bleibt unverändert. Soweit ich weiß, sind foreach-Schleifen auf ihre Rückgabewerte ausgelegt, aber wie kann ich erreichen, dass die Rückgabewerte mit den Positionen übereinstimmen, an denen sich die Werte des Datenrahmens ändern sollten. Bei diesen Werten stimmt das Datum jeder in file_list gelesenen Datei mit den Daten im Datenrahmen DF2 überein. Wenn sie übereinstimmen, wird eine 1 an der bestimmten Position von Zeile (Datum) und Spalte (Dateiname) platziert. Vielen Dank im Voraus für jede Hilfe!

Wunsch Ausgabe lautet:

> DF 
      Date A B C 
1 2016-10-01 1 0 0 
2 2016-10-02 1 0 0 
3 2016-10-03 1 0 0 
4 2016-10-04 1 0 0 
5 2016-10-05 0 0 0 
6 2016-10-06 0 0 0 
7 2016-10-07 0 1 0 
8 2016-10-08 0 1 0 
9 2016-10-09 0 1 0 
10 2016-10-10 0 0 0 
11 2016-10-11 0 0 0 
12 2016-10-12 0 0 0 
13 2016-10-13 0 0 0 
14 2016-10-14 0 0 0 
15 2016-10-15 0 0 1 
16 2016-10-16 0 0 1 
17 2016-10-17 0 0 1 
18 2016-10-18 0 0 1 
19 2016-10-19 0 0 1 
20 2016-10-20 0 0 0 
21 2016-10-21 0 0 0 
22 2016-10-22 0 0 0 
23 2016-10-23 0 0 0 
24 2016-10-24 0 0 0 
25 2016-10-25 0 0 0 
26 2016-10-26 0 0 0 
27 2016-10-27 0 0 0 
28 2016-10-28 0 0 0 
29 2016-10-29 0 0 0 
30 2016-10-30 0 0 0 
31 2016-10-31 0 0 0 
+0

Könnten Sie diesen Teil erklären: „erhalten die Rückgabewerte mit den Standorten entsprechen, wo die Werte der Datenrahmen ändern sollte.“? Vielleicht können Sie ein Beispiel für Ihr gewünschtes Ergebnis geben? –

+0

Natürlich! Diese Werte, nach denen ich suche, sind, wo das Datum jeder Datei, die in 'file_list' gelesen wurde, mit den Daten im Datenrahmen' DF2' übereinstimmt. Wenn sie übereinstimmen, wird eine 1 an der bestimmten Position von Zeile (Datum) und Spalte (Dateiname) platziert. – lurodrig

Antwort

0

Betrachten Null Loops aber ein Reduce() mit merge über alle df Posten der Datenrahmen-Liste. Sie müssen jedoch Ihre Datenrahmen und die Liste etwas anders einrichten.

Zuerst fügen Sie als erstes Elmenet der Liste den sequentiellen Datenrahmen Date hinzu. Fügen Sie dann in jeder Datei, die Sie lesen, eine zweite Spalte hinzu, die A, B, C mit jeweils eins entspricht (was in der lapply- oder for-Schleife, die beim Einleseprozess verwendet wird, gemacht werden kann - stellen Sie diesen Teil zur Demonstration vor). Insgesamt, wie weiter unten mit Original-DF mit all.equal eine exakte Übereinstimmung Ergebnisse gezeigt:

# INITIALIZE LIST WITH DATE SEQUENCE DF 
newldf <- list(data.frame(Date = as.factor(seq(as.POSIXct("2016-10-01", tz = "UTC"), 
            as.POSIXct("2016-10-31", tz = "UTC"), 
            by = 'day')))) 

# APPEND LIST OF DATA FRAMES THAT ARE READ IN, EACH WITH SECOND COL = 1 
newldf <- append(newldf, 
       list(data.frame(Date = c("2016-10-01", "2016-10-02", 
             "2016-10-03", "2016-10-04"), A = 1), 
        data.frame(Date = c("2016-10-07", "2016-10-08", 
             "2016-10-09"), B = 1), 
        data.frame(Date = c("2016-10-15", "2016-10-16", 
             "2016-10-17", "2016-10-18", "2016-10-19"), C=1))) 

# MERGE ALL DATA FAMES TOGETHER 
newDF <- Reduce(function(...) merge(..., by=c("Date"), all=T), newldf) 
newDF[is.na(newDF)] <- 0        # CONVERT NAs TO ZEROs 
newDF$Date <- as.POSIXct(newDF$Date, tz = "UTC")  # CONVERT DATE TO POSIXct 
str(newDF) 
# 'data.frame': 31 obs. of 4 variables: 
# $ Date: POSIXct, format: "2016-10-01" "2016-10-02" ... 
# $ A : num 1 1 1 0 0 0 0 0 0 0 ... 
# $ B : num 0 0 0 0 0 0 1 1 1 0 ... 
# $ C : num 0 0 0 0 0 0 0 0 0 0 ... 

str(DF) 
# 'data.frame': 31 obs. of 4 variables: 
# $ Date: POSIXct, format: "2016-10-01" "2016-10-02" ... 
# $ A : num 1 1 1 0 0 0 0 0 0 0 ... 
# $ B : num 0 0 0 0 0 0 1 1 1 0 ... 
# $ C : num 0 0 0 0 0 0 0 0 0 0 ... 

all.equal(DF, newDF) 
# [1] TRUE 
+0

sieht sehr vielversprechend aus! Was würden Sie jedoch vorschlagen, wenn die Daten, die Sie anhängen, nicht die gleiche Länge haben? Daran arbeite ich und leider bricht der anhängige Prozess an diesem Punkt. Ich habe meine Liste in meiner ursprünglichen Antwort und dem Endziel aktualisiert, um dies zu reflektieren. Ich entschuldige mich dafür, nicht gerade zu denken und die gleichen Mengen an Daten zu verwenden. – lurodrig

+0

Zusammenführen verwendet hier 'all = T'-Argument oder im Grunde einen äußeren Join, so dass Längen von einzelnen Datenrahmen in der Liste ohne ein Problem variieren können. Ich habe die Liste mit Ihren ungleichen Längen aktualisiert und bin ohne Fehler gelaufen. Nicht sicher, was du mit dem Brechen meinst. – Parfait

+0

Entschuldigung! Eine meiner Datendateien hatte keine Werte und die Append-Funktion würde brechen. Ich konnte Ihre Lösung erfolgreich replizieren. Danke für all deine Hilfe! – lurodrig

Verwandte Themen