2016-05-31 12 views
0

Ich versuche, eine Tapply-Funktion anzuwenden, schrieb ich, um ein Dataset zu filtern. Hier ist ein Beispiel Datenrahmen (df) unten, um zu beschreiben, was ich versuche zu tun.Filter Datenrahmen durch Ergebnisse von Tapply Funktion

Ich möchte meine Daten halten, um die Zeilen Frame, in dem der Wert von df $ Cumulative_Time am nächsten zu dem Wert von 14. Es ist dies in df $ ID für jeder Faktor Ebene tun sollte (halten Zeile am nächsten den Wert 14 für jeden ID-Faktor).

ID Date Results TimeDiff Cumulative_Time 
A 7/10/2015 71 0 0 
A 8/1/2015 45 20 20 
A 8/22/2015 0 18 38 
A 9/12/2015 79 17 55 
A 10/13/2015 44 26 81 
A 11/27/2015 98 37 118 
B 7/3/2015 75 0 0 
B 7/24/2015 63 18 18 
B 8/21/2015 98 24 42 
B 9/26/2015 70 30 72 
C 8/15/2015 77 0 0 
C 9/2/2015 69 15 15 
C 9/4/2015 49 2 17 
C 9/8/2015 88 2 19 
C 9/12/2015 41 4 23 
C 9/19/2015 35 6 29 
C 10/10/2015 33 18 47 
C 10/14/2015 31 3 50 
D 7/2/2015 83 0 0 
D 7/28/2015 82 22 22 
D 8/27/2015 100 26 48 
D 9/17/2015 19 17 65 
D 10/8/2015 30 18 83 
D 12/9/2015 96 51 134 
D 1/6/2016 30 20 154 
D 2/17/2016 32 36 190 
D 3/19/2016 42 27 217 

Ich habe so weit wie die folgende:

spec_day = 14 # value I want to compare df$Cumulative_Time to 


# applying function to calculate closest value to spec_day 
    tapply(df$Cumulative_Time, df$ID, function(x) which(abs(x - spec_day) == min(abs(x - spec_day)))) 

Frage: Wie füge ich diese tapply Funktion als Mittel zur Filterung von meinem Datenrahmen df zu tun? Gehe ich dieses Problem auf die richtige Art an, oder gibt es einen einfacheren Weg, dies zu erreichen, den ich nicht sehe? Jede Hilfe wäre willkommen - danke!

+0

Wenn Sie mit R Basissprache halten möchten, können Sie mit einem Blick auf 'split (df df $ ID)' dann haben ' Verwenden Sie Ihren Ansatz, um Indizes abzurufen, die einer bestimmten ID entsprechen: result <- lapply (mysplit, FUN = Funktion (df) {df [which() ...,]}) '. Kombinieren Sie schließlich alle gefilterten Daten mit einem 'do.call (" rbind ", result)'. Ich würde ermutigen, zu untersuchen "data.table" Optionen –

+0

Danke, @EricLecoutre! Ich erinnere mich daran, über Split() gelesen zu haben, also werde ich diese Methode auch ausprobieren! – soitgoes

Antwort

2

Hier ist eine Art und Weise können Sie es tun, beachten Sie, dass ich nicht tapply verwendet haben:

spec_day <- 14 
new_df <- do.call('rbind', 
      by(df, df$ID, 
      FUN = function(x) x[which.min(abs(x$Cumulative_Time - spec_day)), ] 
      )) 
new_df 

    ID  Date Results TimeDiff Cumulative_Time 
A A 8/1/2015  45  20    20 
B B 7/24/2015  63  18    18 
C C 9/2/2015  69  15    15 
D D 7/28/2015  82  22    22 

which.min (und seine Geschwister which.max) eine sehr nützliche Funktion ist.

+0

Danke, @bouncyball! Ich denke ich verstehe was.min - danke, dass du mich auf diese Funktion aufmerksam gemacht hast und mir einen anderen Ansatz für dieses Problem gegeben hast! – soitgoes

1

Hier ist eine kurze und schnellere Alternative mit data.table:

library(data.table) 
setDT(df)[, .SD[which.min(abs(Cumulative_Time - 14))], by = ID] 
# ID  Date Results TimeDiff Cumulative_Time 
#1: A 8/1/2015  45  20    20 
#2: B 7/24/2015  63  18    18 
#3: C 9/2/2015  69  15    15 
#4: D 7/28/2015  82  22    22 
+0

Danke, @ Mtoto! Ich mag die Prägnanz dieses hier. Es ist auch ziemlich intuitiv zu verstehen, was der Code tut! – soitgoes