dplyr filtre: Obtenir des lignes avec un minimum de variable, mais seulement la première si minima multiples

Je veux faire un groupe de filtre à l'aide de dplyr, de manière que, dans chaque groupe, seulement cette ligne est renvoyée, qui a la valeur minimale de la variable x.

Mon problème est le suivant: Comme prévu, dans le cas de plusieurs minima tous lignes avec la valeur minimale sont retournés. Mais dans mon cas, je veux seulement la première ligne si plusieurs minima sont présents.

Voici un exemple:

df <- data.frame(
A=c("A", "A", "A", "B", "B", "B", "C", "C", "C"),
x=c(1, 1, 2, 2, 3, 4, 5, 5, 5),
y=rnorm(9)
)

library(dplyr)
df.g <- group_by(df, A)
filter(df.g, x == min(x))

Comme prévu, tous les minima sont de retour:

Source: local data frame [6 x 3]
Groups: A

  A x           y
1 A 1 -1.04584335
2 A 1  0.97949399
3 B 2  0.79600971
4 C 5 -0.08655151
5 C 5  0.16649962
6 C 5 -0.05948012

Avec ddply, j'aurais approche de la tâche de cette façon:

library(plyr)
ddply(df, .(A), function(z) {
    z[z$x == min(z$x), ][1, ]
})

... qui fonctionne:

  A x           y
1 A 1 -1.04584335
2 B 2  0.79600971
3 C 5 -0.08655151

Q: Est-il une façon d'aborder cette question dans dplyr? (Pour des raisons de vitesse)

  • filter(df.g, rank(x) == 1) ?
  • Merci. Je savais qu'il y aurait une solution facile 😉
  • ne rank(x)==1 donner les résultats escomptés?
  • il nécessite ties=first argument. FelixS, si vous allez pour la vitesse, rank est une mauvaise idée de calcul de plus en plus exigeants que min (ou) which.min.
  • En fait, vous voulez probablement min_rank(). @Arun: dplyr fournit une mise en œuvre interne de min_rank() qui devrait être beaucoup assez rapide.
  • 1) je ne pense pas que min_rank aide ici. Il a besoin de la première valeur min (regardez plyr solution). 2) quel que soit le langage de programmation que vous écrivez, la complexité algorithmique de rank (liens=min, max, le premier, etc..) sera plus grand que juste l'informatique min.
  • prématuré d'optimisation est ...
  • pas de vous suivre.
  • Vrai, seulement rank(x, ties.method="first")==1 œuvres, comme min et min_rank ne font pas de distinction entre plusieurs minima.
  • la droite. Mais c'est assez cher (parce que c'est de trier toutes les valeurs pour chaque groupe). Vous devriez être en utilisant which.min. Mais je ne sais pas d'une dplyr solution. Un plyr cas serait: ddply(df, .(A), function(z) z[which.min(z$x), ])
  • c'est en supposant qu'un temps O(n lg n) algorithme effectuez beaucoup plus de mal qu'un algorithme O(n) sans plus d'informations sur le domaine
  • Désolé, j'étais en train de penser de row_number() - c'est l'équivalent de rank(ties = "first") mais être mis en œuvre de manière plus efficace en C++.
  • Je ne vois pas comment cela vous fait envisager which.min être prématuré d'optimisation. Autant que je sache, c'est un choix naturel, agréable à lire, facile à comprendre, rapide, comme il arrive à O(n) trop.

InformationsquelleAutor Felix S | 2014-01-23