J'ai le dataframe suivant:
z x u y 0 0 1 0 0 0 0 1 0 0 1 0 1 1 1 1 0 1 1 1 2 1 1 1 1 3 0 0 1 1 4 0 0 1 1 5 0 0 0 0 7 0 1 1 1 7 0 1 1 1 8 1 1 0 0 9 0 1 1 1 9 0 1 1 1
zs = ['z','x'] tf = ds[ds[zs].values == (0,1)] tf
Comment sélectionner des lignes qui ont les valeurs (0,1) pour les noms de variables spécifiés dans une liste?
Voici ce que j'ai jusqu'à présent:
z x u y 0 0 1 0 0 1 0 1 1 1 2 1 1 1 1 3 0 0 1 1 4 0 0 1 1 5 0 0 0 0 6 1 0 1 1 7 0 1 1 1 8 1 1 0 0 9 0 1 1 1
Maintenant qui imprime:
import pandas as pd
import numpy as np
ds = pd.DataFrame({'z':np.random.binomial(n=1,p=0.5,size=10),
'x':np.random.binomial(n=1,p=0.5,size=10),
'u':np.random.binomial(n=1,p=0.5,size=10),
'y':np.random.binomial(n=1,p=0.5,size=10)})
ds
Qui montre les doublons et a également une ligne incorrecte (ligne # 2 - 1,1,1,1). Des pensées ou des idées? Bien sûr, je suppose qu'il existe une manière pythonique de faire cela sans boucles imbriquées et sans forcer brutalement.
4 Réponses :
Vous pouvez faire:
cols = ['u','x'] bools = ds[cols].apply(lambda x: all(x == (0,1)), axis=1) ds[bools] u x y z 0 0 1 1 1 7 0 1 0 1 8 0 1 1 0
Vous pouvez utiliser la comparaison numpy diffusée:
querystr = ' and '.join([f'{c} == {v!r}' for c, v in zip(cols, vals)])
df.query(querystr)
z x u y
0 0 1 0 0
1 0 1 1 1
7 0 1 1 1
9 0 1 1 1
Vous pouvez également utiliser np.logical_and.reduce:
cols = ['z', 'x'] vals = [0, 1] df[np.logical_and.reduce([df[c] == v for c, v in zip(cols, vals)])] z x u y 0 0 1 0 0 1 0 1 1 1 7 0 1 1 1 9 0 1 1 1
Merci @coldspeed. C'est très utile. Savez-vous pourquoi ma requête simpliste donne la mauvaise réponse (doublons et ligne erronée)?
@vsm Vous étiez proche. Vous avez besoin d'un masque 1D pour indexer df . Ainsi, avec votre solution, vous auriez dû faire (df [['z', 'x']]. Values == (0, 1)). All (axis = 1) pour voir lequel row satisfait à cette condition pour toutes les colonnes. C'est pourquoi c'était ma première option: vous montrer votre code fixe.
En utilisant eq , et très similaire à la méthode numpy de Cold
df[df[zs].eq(pd.Series([0,1],index=zs),1).all(1)] z x u y 0 0 1 0 0 1 0 1 1 1 7 0 1 1 1 9 0 1 1 1
Un moyen plus simple consiste à utiliser l ' indexation booléenne :
f = ds['z'] == 0 g = ds['x'] == 1 ds[f & g]
"simple" mais ne s'adapte pas à plusieurs colonnes et valeurs. Voir np.logical_and.reduce pour savoir comment le généraliser (voir aussi la deuxième option de ma réponse).