7
votes

Nettoyer la trame de données de sorte que dans une colonne, aucune valeur de ligne ne soit plus grande que 2 fois la valeur de la ligne suivante

J'ai une trame de données illustrée par le suivant

df<-cleaner(df,"dist",2)


1 commentaires

Pouvez-vous essayer correctement () fonctionner? Vous pouvez simplement le faire manuellement si le cadre de données n'est pas si gros.


3 Réponses :


5
votes

Vous pouvez essayer diriger code> à partir de dplyr code> xxx pré>

ou en utilisant la même méthode dans data.able code> . Une nouvelle fonction shift code> est introduite dans la version Devel de données.table. Nous pouvons spécifier le type à dirigeant code>. Par défaut, il est retard code> et remplissage code> est na. Modifiez le remplir code> sur 'INF' (inspiré du message d'@marat Talipov). P>

set.seed(49)
df <- data.frame(id='A', dist=rnorm(1e7,20))
df1 <- copy(df)
akrun1 <- function() {filter(df, dist < 2 * lead(dist,
                                 default = Inf)) }
akrun2 <- function() {setDT(df1)[dist <2 *shift(dist,type='lead',
                                     fill=Inf)]}
marat <- function() {subset(df,dist < c(2*dist[-1],Inf))}
Colonel <- function() {df[with(df, dist<2*c(dist[-1], tail(dist,1))),]}

library(microbenchmark)
microbenchmark(akrun1(), akrun2(), marat(), Colonel(), 
                                unit='relative', times=20L)
#Unit: relative
#    expr      min       lq     mean   median       uq      max neval  cld
# akrun1() 2.029087 1.990739 1.864697 1.965247 1.773722 1.727474    20  b  
# akrun2() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    20  a   
# marat() 8.032147 8.137982 7.359821 7.937062 7.134686 5.837623     20  d
#Colonel() 7.094465 7.045000 6.473552 6.903460 6.197737 5.359575    20  c 


3 commentaires

@Henrik vous avez raison. Merci. Toutes les solutions actuelles ne renvoient que les 2 valeurs.


Filtre (DF, DIST <2 * LEAD (DIST, Par défaut = INF)) Fonctionne pour moi


@hadley Merci beaucoup, j'ai utilisé la version dplyr, car ma trame de données avait plusieurs sous-groupes, il semblait naturel. La seule chose est que je dois filtrer plusieurs fois; Lorsque des valeurs> 2 * Les plomb sont filtrées, la trame de données résultante peut introduire de nouvelles occurrences de valeurs principales inférieures à 2 * la valeur de retard. Ce n'était pas le cas dans mon exemple, donc mon mauvais. Merci encore pour vos réponses rapides et excellentes.



6
votes

Vous pouvez déplacer votre DIST code> Colonne Un élément à gauche, multipliez-le par deux, et comparez-le avec l'original dist code>:

subset(df,dist < c(2*dist[-1],Inf))
#  id dist
#1  A  1.1
#2  A  1.0
#5  A  2.1
#7  A  3.3
#8  A  3.4


0 commentaires

3
votes

une solution de base r: xxx

s'il n'y a pas d'éléments zéro: xxx


2 commentaires

Mais que si certains dist sont des zéros?


Exactement, votre solution de multiplication est meilleure pour le cas général!