filtrage à l'aide de plusieurs conditions sur plusieurs colonnes à l'aide de dplyr
J'ai cherché sur DONC essayer de trouver une solution en vain. Si elle est ici. J'ai un bloc de données avec de nombreuses colonnes, dont certaines sont numériques et ne doit pas être négative. Je veux nettoyer les données depuis quelques valeurs dans ces numérique colonnes sont négatifs. Ce que je peux faire maintenant est d'extraire les noms de colonnes de ces colonnes avec une expression régulière. Mais je ne suis pas sûr de la façon de mettre en œuvre le filtrage de lignes sur la base de ces colonnes.
Pour donner un exemple, nous allons dire:
library(dplyr)
df <- read.table(text =
"id sth1 tg1_num sth2 tg2_num others
1 dave 2 ca 35 new
2 tom 5 tn -3 old
3 jane -3 al 0 new
4 leroy 0 az 25 old
5 jerry 4 mi 55 old", header=TRUE)
pattern <- "_num$"
ind <- grep(pattern, colnames(df))
target_columns <- colnames(df)[ind]
df <- df %>% filter(target_columns >= 0) # it's is wrong, but it's what I want to do
Ce que je veux sortir de ce filtrage est la suivante:
id sth1 tg1_num sth2 tg2_num others
1 dave 2 ca 35 new
4 leroy 0 az 25 old
5 jerry 4 mi 55 old
où les lignes ne. 2 et 3 ne sont pas filtrées, parce que au moins une colonne en tg1_num et tg2_num pour ces lignes contiennent des nombres négatifs.
df %>%select(matches("_num$"))
?Qu'est-ce que le résultat désiré? Voulez-vous le dos ou tout simplement celles correspondant au modèle? Voulez-vous les deux colonnes à être plus grande ou égale à zéro, ou un seul suffit? Merci de nous montrer le produit final
c'est une façon de sélectionner les colonnes cibles. Mais ne résout pas mon problème
OriginalL'auteur breezymri | 2015-08-19
Vous devez vous connecter pour publier un commentaire.
C'est un très maladroit utilisation de
dplyr
, mais peut-être fidèle à l'espritÀ partir de là, vous pouvez ajouter un
filter(m >= 0)
pour obtenir la réponse que vous voulez. Si il y avait unrowMins
analogue àrowMeans
alors ce serait simplifier de manière significative.Je ne sais pas comment efficace, c'est, bien. Et l'imbrication de la
select
semble réel laid.EDIT3: en Utilisant les idées chipé à partir d'autres solutions/commentaires (h/t @Vlo) je peux la vitesse de la mine de beaucoup (malheureusement, une telle optimisation des vitesses allant jusqu' @Vlo de solution encore plus (EDIT4: Oups, mal lu le tableau, je suis le plus rapide, ok, pas plus à ce sujet))
EDIT: par curiosité, certains n'ont microbenchmarking sur certaines des solutions (EDIT2: Ajout de solutions)
Et voici les définitions que j'ai utilisé
df
doit contenir le négatif et le positif entier (pas de petites décimales) des valeurs comme l'OP de l'échantillon de données.superreducer <- function(df) { df %>% select(matches("_num$")) %>% Reduce(bitwOr, .) %>% {.>=0L} %>% which %>% slice(.data = df) }
est 20% plus rapide quereducer()
Quel est le sens de l'accolades autour de
{df[. >= 0,]}
?C'est un magrittr caprice; si vous exécutez une pipe à un bloc anonyme (c'est à dire entre accolades) le résultat de la commande précédente est stocké dans
.
--3 %>% { . + 1 }
rendements4
. C'est donc dire filtre pour toutes les lignes où l'élément précédent est supérieur à zéro.OriginalL'auteur user295691
Voici une possible vectorisé solution
L'idée ici est de créer une logique de la matrice à l'aide de la
<
fonction (c'est une fonction générique qui adata.frame
méthode, ce qui signifie qu'il retourne d'un bloc de données comme la structure à l'arrière). Ensuite, nous utilisonsrowSums
à trouver si il y avait un d'eux correspond à des conditions (> 0 - correspondance, 0 - non appariés). Ensuite, nous utilisons le!
fonction, afin de le convertir à une logique de vecteur: >0 devientTRUE
, tandis que 0 devientFALSE
. Enfin, nous sommes. en fonction de ce vecteur.OriginalL'auteur David Arenburg
Je voulais voir ce qui a été possible en utilisant la norme d'évaluation avec dplyr de
filter_
. Il s'avère qu'il peut être fait avec l'aide deinterp
de lazyeval, à la suite de la exemple de code sur cette page. Essentiellement, vous devez créer une liste de lainterp
conditions qui vous passent ensuite au.dots
argument defilter_
.Mise à jour
De départ avec dplyr_0.7, ce qui peut être fait directement avec
filter_at
etall_vars
(pas de lazyeval nécessaire).OriginalL'auteur aosmith
À l'aide de la base de R pour obtenir votre résultat
Edit: cela suppose que vous avez plusieurs colonnes avec "_num". Il ne fonctionnera pas si vous avez juste un _num colonne
OriginalL'auteur Whitebeard
Nous avons d'abord créer un index de toutes les colonnes numériques. Ensuite, nous sous-ensemble de toutes les colonnes d'une plus grande ou égale à zéro. Donc, il n'est pas nécessaire de vérifier les noms de colonne et la colonne id sera toujours positif.
De sortie:
OriginalL'auteur mpalanco
Voici mon laid solution. Suggestions/critiques bienvenue
Nvm, qui ressemble + tranche de beats sur la base de sous-ensemble de R par une très importante marge
OriginalL'auteur Vlo
Cela vous donnera un vecteur de lignes qui sont inférieures à 0:
Alors d'obtenir un df de votre choix à l'lignes:
mis à jour pour utiliser les appliquer
Juste par intérêt, pensez-vous que l'on pouvait aussi utiliser
filter(...)
dans votre première ligne de code?OriginalL'auteur Tchotchke