J'ai le cadre de données suivant:
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
maintenant, je dois créer une quatrième colonne et insérer la date de transaction maximale pour chaque id
dans celle-ci. La table finale devrait être comme suit:
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
Je serais reconnaissant si vous pouviez m'aider avec ceci.
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
Éditer: puisque vous voulez que la dernière colonne soit "vide" lorsque la date ne correspond pas à la date maximale, vous pouvez essayer la ligne suivante.
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
Bien sûr, il est toujours agréable de nettoyer les noms de pays, etc., mais je vous laisse cela.
Une autre approche consiste à utiliser le package plyr
:
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
Maintenant, ce n’est pas dans le format que vous recherchiez, car il ne montre que chaque id
une fois. Ne craignez rien, nous pouvons utiliser transform
au lieu de summarize
:
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
Comme dans la réponse de @ seandavi, cela répète la date max
pour chaque id
. Si vous souhaitez modifier les doublons en NA
, une chose comme celle-ci fera l'affaire:
within(ddply(df, "id", transform, max = max(date2)), max[max != date2] <- NA)
Ajout de la solution dplyr
au cas où quelqu'un regarderait:
library(dplyr)
df %>%
group_by(id) %>%
mutate(max = if_else(date2 == max(date2), date2, as.Date(NA)))
Résultat:
# 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
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>
Vous ne pouvez pas utiliser 0 comme valeur de date. Vous devrez donc abandonner la conservation comme date ou accepter une valeur NA:
# 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"
La machine ifelse
effectue une vérification de type étrange qui échoue en utilisant simplement x
comme deuxième argument ci-dessus, mais renvoie toujours le vecteur Date-class. Allez comprendre! Ci-dessous, l’option de vecteur de caractère.
# 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"
J'ai trouvé ceci pour m'aider quand je veux voir la date min/max d'une colonne
Max: head(df %>% distinct(date) %>% arrange(desc(date)))
Min: head(df %>% distinct(date) %>% arrange(date))
Le max va trier la colonne de date par ordre décroissant, vous permettant de voir le max. Le min va trier par ordre croissant, vous permettant de voir le min.
Vous devez utiliser le package dplyr
pour cela.