2012-08-26 5 views
12

Ich habe folgenden Datenrahmen:Finden Sie die max Datum für jede ID

id<-c(1,1,2,3,3) 
date<-c("23-01-08","01-11-07","30-11-07","17-12-07","12-12-08") 
df<-data.frame(id,date) 
df$date2<-as.Date(as.character(df$date), format = "%d-%m-%y") 


id  date  date2 
1 23-01-08 2008-01-23 
1 01-11-07 2007-11-01 
2 30-11-07 2007-11-30 
3 17-12-07 2007-12-17 
3 12-12-08 2008-12-12 

jetzt brauche ich eine vierte Spalte erstellen und für jeden id, dass maximal Datum der Transaktion ein. der Final Table sollte wie folgt sein:

id  date  date2  max 
1 23-01-08 2008-01-23 2008-01-23 
1 01-11-07 2007-11-01 0 
2 30-11-07 2007-11-30 2007-11-30 
3 17-12-07 2007-12-17 0 
3 12-12-08 2008-12-12 2008-12-12 

ich dankbar sein würde, wenn Sie mir dabei helfen könnte.

Antwort

18
id<-c(1,1,2,3,3) 
date<-c("23-01-08","01-11-07","30-11-07","17-12-07","12-12-08") 
df<-data.frame(id,date) 
df$date2<-as.Date(as.character(df$date), format = "%d-%m-%y") 
# aggregate can be used for this type of thing 
d = aggregate(df$date2,by=list(df$id),max) 
# And merge the result of aggregate 
# with the original data frame 
df2 = merge(df,d,by.x=1,by.y=1) 
df2 

    id  date  date2   x 
1 1 23-01-08 2008-01-23 2008-01-23 
2 1 01-11-07 2007-11-01 2008-01-23 
3 2 30-11-07 2007-11-30 2007-11-30 
4 3 17-12-07 2007-12-17 2008-12-12 
5 3 12-12-08 2008-12-12 2008-12-12 

Edit: Da Sie die letzte Spalte zu „leer“ sein soll, wenn das Datum nicht das max Datum übereinstimmt, können Sie die nächste Zeile versuchen.

df2[df2[,3]!=df2[,4],4]=NA 

df2 
    id  date  date2   x 
1 1 23-01-08 2008-01-23 2008-01-23 
2 1 01-11-07 2007-11-01  <NA> 
3 2 30-11-07 2007-11-30 2007-11-30 
4 3 17-12-07 2007-12-17  <NA> 
5 3 12-12-08 2008-12-12 2008-12-12 

Natürlich ist es immer schön, die COLNAMES aufzuräumen, etc., aber ich lasse das für Sie.

2
library(sqldf) 
tables<- '(SELECT * FROM df 
      ) 
      AS t1, 
      (SELECT id,max(date2) date2 FROM df GROUP BY id 
      ) 
      AS t2' 

out<-fn$sqldf("SELECT t1.*,t2.date2 mdate FROM $tables WHERE t1.id=t2.id") 
out$mdate<-as.Date(out$mdate) 
out$mdate[out$date2!=out$mdate]<-NA 
# id  date  date2  mdate 
#1 1 01-11-07 2007-11-01  <NA> 
#2 1 23-01-08 2008-01-23 2008-01-23 
#3 2 30-11-07 2007-11-30 2007-11-30 
#4 3 12-12-08 2008-12-12 2008-12-12 
#5 3 17-12-07 2007-12-17  <NA> 
1

Sie können nicht 0 als Date-Wert verwenden, so müssen Sie entweder aufgeben müssen, um es als Datum zu halten oder einen NA-Wert annehmen:

# Date values: 
df$maxdt <- ave(df$date2, df$id, 
        FUN=function(x) ifelse(x == max(x), as.character(x), NA)) 
str(ave(df$date2, df$id, FUN=function(x) ifelse(x == max(x), as.character(x), NA))) 
# Date[1:5], format: "2008-01-23" NA "2007-11-30" NA "2008-12-12" 

Die ifelse Maschinen hat einige seltsame Art Überprüfung, dass besiegt nur x als zweites Argument oben, gibt aber immer noch den Date-Class-Vektor zurück. Stelle dir das vor! Unten ist die Zeichenvektoroption.

# Character values: 
df$maxdt <- ave(as.character(df$date2), df$id, 
        FUN=function(x) ifelse(x == max(x), x, "0")) 
ave(as.character(df$date2), df$id, FUN=function(x) ifelse(x == max(x), x, "0")) 
[1] "2008-01-23" "0"   "2007-11-30" "0"   "2008-12-12" 
7

Ein weiterer Ansatz ist es, das plyr Paket zu verwenden:

library(plyr) 
ddply(df, "id", summarize, max = max(date2)) 

# id  max 
#1 1 2008-01-23 
#2 2 2007-11-30 
#3 3 2008-12-12 

Nun ist dies nicht im Format, das Sie nach dem waren, da es nur jeden id einmal zeigt. Keine Angst, wir transform statt summarize verwenden:

ddply(df, "id", transform, max = max(date2)) 

# id  date  date2  max 
#1 1 01-11-07 2007-11-01 2008-01-23 
#2 1 23-01-08 2008-01-23 2008-01-23 
#3 2 30-11-07 2007-11-30 2007-11-30 
#4 3 12-12-08 2008-12-12 2008-12-12 
#5 3 17-12-07 2007-12-17 2008-12-12 

Wie in @ seandavi Antwort, diese wiederholt das max Datum für jeden id. Wenn Sie die Duplikate zu NA ändern wollen, wie etwas, das wird die Arbeit erledigen:

within(ddply(df, "id", transform, max = max(date2)), max[max != date2] <- NA) 
2

dplyr Lösung, falls jemand Hinzufügen sucht:

library(dplyr) 

df %>% 
    group_by(id) %>% 
    mutate(max = if_else(date2 == max(date2), date2, as.Date(NA))) 

Ergebnis:

# A tibble: 5 x 4 
# Groups: id [3] 
    id  date  date2  max 
    <dbl> <fctr>  <date>  <date> 
1  1 23-01-08 2008-01-23 2008-01-23 
2  1 01-11-07 2007-11-01   NA 
3  2 30-11-07 2007-11-30 2007-11-30 
4  3 17-12-07 2007-12-17   NA 
5  3 12-12-08 2008-12-12 2008-12-12 
+0

Ich benutze es so: muate (flag_last = if_else (date == max (Datum), TRUE, FALSE))%>% filter (flag_last == TRUE) – Rohit