Question
En utilisant dplyr
, comment sélectionner les observations / lignes du haut et du bas de données groupées dans une instruction?
Données et exemple
Étant donné une trame de données
df <- data.frame(id=c(1,1,1,2,2,2,3,3,3),
stopId=c("a","b","c","a","b","c","a","b","c"),
stopSequence=c(1,2,3,3,1,4,3,1,2))
Je peux obtenir les observations du haut et du bas de chaque groupe en utilisant slice
, mais en utilisant deux déclarations distinctes:
firstStop <- df %>%
group_by(id) %>%
arrange(stopSequence) %>%
slice(1) %>%
ungroup
lastStop <- df %>%
group_by(id) %>%
arrange(stopSequence) %>%
slice(n()) %>%
ungroup
Puis-je combiner ces deux statmenets en un seul qui sélectionne les observations du haut et du bas?
Réponses:
Il existe probablement un moyen plus rapide:
la source
rownumber() %in% c(1, n())
éviterait la nécessité d'exécuter deux fois l'analyse vectorielle_
? iefilter(row_number() %in% c(1, n()))
Juste pour être complet: vous pouvez passer
slice
un vecteur d'indices:qui donne
la source
filter
- je n'ai pas testé cela, mais voir icimtcars[1, ] %>% slice(c(1, n()))
, dans ce sens, le choix entre eux dépend de ce que vous voulez retourner. Je m'attendrais à ce que les horaires soient proches à moins que ce nen
soit très grand (où la tranche pourrait être favorisée), mais je n'ai pas testé non plus.Non
dplyr
, mais c'est beaucoup plus direct en utilisantdata.table
:Explication plus détaillée:
Assurez-vous de consulter le wiki de mise en route pour connaître les
data.table
basesla source
df[ df[order(stopSequence), .I[c(1,.N)], keyby=id]$V1 ]
. Voirid
apparaître deux fois est bizarre pour moi.setDT
appel. Donc unorder
appel pas besoin ici.df[order(stopSequence), .SD[c(1L,.N)], by = id]
. Voir iciid
. Je pense quedf[order(stopSequence), .SD[c(1L, .N)], keyby = id]
ça devrait faire l'affaire (avec la petite différence avec la solution ci-dessus, le résultat serakey
edQuelque chose comme:
Avec
do
vous pouvez effectuer à peu près n'importe quel nombre d'opérations sur le groupe, mais la réponse de @ jeremycg est bien plus appropriée pour cette tâche.la source
slice
, commedf %>% arrange(stopSequence) %>% group_by(id) %>% slice(c(1,n()))
do
exemple ici pourrait aider les autres quandslice
cela ne fonctionnera pas (c'est-à-dire des opérations plus complexes sur un groupe). Et, vous devriez poster votre commentaire comme réponse (c'est la meilleure).Je connais la question spécifiée
dplyr
. Mais, comme d'autres ont déjà publié des solutions utilisant d'autres packages, j'ai décidé d'essayer également d'autres packages:Paquet de base:
data.table:
sqldf:
En une seule requête:
Production:
la source
en utilisant
which.min
etwhich.max
:référence
C'est également beaucoup plus rapide que la réponse acceptée actuelle car nous trouvons les valeurs min et max par groupe, au lieu de trier toute la colonne stopSequence.
la source
Utilisation
data.table
:la source
Une autre approche avec lapply et une déclaration de dplyr. Nous pouvons appliquer un nombre arbitraire de toutes les fonctions récapitulatives à la même instruction:
Vous pouvez par exemple vous intéresser également aux lignes avec la valeur max stopSequence et faire:
la source
Une alternative de base R différente serait de commencer
order
parid
etstopSequence
,split
en fonction deid
et pour chaque,id
nous sélectionnons uniquement le premier et le dernier index et sous-ensemble la trame de données en utilisant ces indices.Ou utilisation similaire
by
la source