11 votes

sélectionner la dernière observation dans les données longitudinales

Je dispose d'un ensemble de données comportant plusieurs évaluations temporelles pour chaque participant. Je souhaite sélectionner la dernière évaluation pour chaque participant. Mon jeu de données ressemble à ceci :

ID  week  outcome
1   2   14
1   4   28
1   6   42
4   2   14
4   6   46
4   9   64
4   9   71
4  12   85
9   2   14
9   4   28
9   6   51
9   9   66
9  12   84

Je veux sélectionner uniquement la dernière observation/évaluation pour chaque participant, mais je n'ai que le nombre de semaines comme indicateur pour chaque participant. Comment est-ce possible dans R (ou excel ?)?

Merci d'avance,

niki

1voto

Tyler Rinker Points 27607

J'ai essayé d'utiliser un peu plus les fonctions "split" et "tapply" pour me familiariser avec elles. Je sais que cette question a déjà reçu une réponse mais j'ai pensé ajouter une autre solution en utilisant split (pardonnez la laideur ; je suis plus qu'ouvert aux commentaires pour l'amélioration ; j'ai pensé qu'il y avait peut-être une utilité à tapply pour alléger le code) :

sdf <-with(df, split(df, ID))
max.week <- sapply(seq_along(sdf), function(x) which.max(sdf[[x]][, 'week']))
data.frame(t(mapply(function(x, y) y[x, ], max.week, sdf)))

Je me suis également demandé pourquoi nous avions 7 réponses ici, c'était mûr pour une analyse comparative. Les résultats peuvent vous surprendre (en utilisant rbenchmark avec R2.14.1 sur une machine Win 7) :

# library(rbenchmark)
# benchmark(
#     DATA.TABLE= {dt <- data.table(df, key="ID")
#         dt[, .SD[which.max(outcome),], by=ID]},
#     DO.CALL={do.call("rbind", 
#         by(df, INDICES=df$ID, FUN=function(DF) DF[which.max(DF$week),]))},
#     PLYR=ddply(df, .(ID), function(X) X[which.max(X$week), ]),
#     SPLIT={sdf <-with(df, split(df, ID))
#         max.week <- sapply(seq_along(sdf), function(x) which.max(sdf[[x]][, 'week']))
#         data.frame(t(mapply(function(x, y) y[x, ], max.week, sdf)))},
#     MATCH.INDEX=df[rev(rownames(df)),][match(unique(df$ID), rev(df$ID)), ],
#     AGGREGATE=df[cumsum(aggregate(week ~ ID, df, which.max)$week), ],
#     #WHICH.MAX.INDEX=df[sapply(unique(df$ID), function(x) which.max(x==df$ID)), ],
#     BRYANS.INDEX = df[cumsum(as.numeric(lapply(split(df$week, df$ID), 
#         which.max))), ],
#     SPLIT2={sdf <-with(df, split(df, ID))
#         df[cumsum(sapply(seq_along(sdf), function(x) which.max(sdf[[x]][, 'week']))),
#         ]},
#     TAPPLY=df[tapply(seq_along(df$ID), df$ID, function(x){tail(x,1)}),],
# columns = c( "test", "replications", "elapsed", "relative", "user.self","sys.self"), 
# order = "test", replications = 1000, environment = parent.frame())

          test replications elapsed  relative user.self sys.self
6    AGGREGATE         1000    4.49  7.610169      2.84     0.05
7 BRYANS.INDEX         1000    0.59  1.000000      0.20     0.00
1   DATA.TABLE         1000   20.28 34.372881     11.98     0.00
2      DO.CALL         1000    4.67  7.915254      2.95     0.03
5  MATCH.INDEX         1000    1.07  1.813559      0.51     0.00
3         PLYR         1000   10.61 17.983051      5.07     0.00
4        SPLIT         1000    3.12  5.288136      1.81     0.00
8       SPLIT2         1000    1.56  2.644068      1.28     0.00
9       TAPPLY         1000    1.08  1.830508      0.88     0.00

Éditer1 : J'ai omis la solution WHICH MAX car elle ne renvoie pas les bons résultats et j'ai renvoyé une solution AGGREGATE que je voulais utiliser (avec les compliments de Bryan Goodrich) et une version actualisée de split, SPLIT2, qui utilise cumsum (j'ai aimé ce changement).

Editer 2 : Dason a également fait part d'une solution d'application que j'ai proposée dans le cadre du test et qui s'est avérée très efficace.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X