Comment «sélectionner distinct» sur plusieurs colonnes de trame de données dans les pandas?

104

Je cherche un moyen de faire l'équivalent du SQL

SELECT DISTINCT col1, col2 FROM dataframe_table

La comparaison pandas sql n'a rien à propos de distinct.

.unique() ne fonctionne que pour une seule colonne, donc je suppose que je pourrais concaténer les colonnes, ou les mettre dans une liste / tuple et comparer de cette façon, mais cela semble être quelque chose que les pandas devraient faire de manière plus native.

Est-ce que je manque quelque chose d'évident ou n'y a-t-il aucun moyen de le faire?

Jody
la source
Vous auriez à faire quelque chose comme, df.apply(pd.Series.unique)mais cela ne fonctionnera pas si le nombre de valeurs uniques varie d'une colonne à l'autre, vous devrez donc construire un dict des noms de colonnes en tant que clés et des valeurs uniques en tant que valeurs
EdChum
Documentation SO
user2314737

Réponses:

175

Vous pouvez utiliser la drop_duplicatesméthode pour obtenir les lignes uniques dans un DataFrame:

In [29]: df = pd.DataFrame({'a':[1,2,1,2], 'b':[3,4,3,5]})

In [30]: df
Out[30]:
   a  b
0  1  3
1  2  4
2  1  3
3  2  5

In [32]: df.drop_duplicates()
Out[32]:
   a  b
0  1  3
1  2  4
3  2  5

Vous pouvez également fournir l' subsetargument mot - clé si vous souhaitez utiliser uniquement certaines colonnes pour déterminer l'unicité. Voir la docstring .

joris
la source
5
Il est peut-être intéressant de noter que, df.drop_duplicates()par défaut, ce n'est pas une méthode inplace, donc renvoie un nouveau DataFrame (en laissant dfinchangé). C'est un comportement assez standard, mais qui peut encore être utile.
evophage
14

J'ai essayé différentes solutions. Le premier était:

a_df=np.unique(df[['col1','col2']], axis=0)

et cela fonctionne bien pour les données non-objet Une autre façon de faire cela et d'éviter les erreurs (pour le type de colonnes objet) est d'appliquer drop_duplicates ()

a_df=df.drop_duplicates(['col1','col2'])[['col1','col2']]

Vous pouvez également utiliser SQL pour ce faire, mais cela a fonctionné très lentement dans mon cas:

from pandasql import sqldf
q="""SELECT DISTINCT col1, col2 FROM df;"""
pysqldf = lambda q: sqldf(q, globals())
a_df = pysqldf(q)
Portefeuille Yury
la source
7

Il n'y a pas de uniqueméthode pour un df, si le nombre de valeurs uniques pour chaque colonne était le même, alors ce qui suit fonctionnerait: df.apply(pd.Series.unique)mais sinon, vous obtiendrez une erreur. Une autre approche serait de stocker les valeurs dans un dict qui est indexé sur le nom de la colonne:

In [111]:
df = pd.DataFrame({'a':[0,1,2,2,4], 'b':[1,1,1,2,2]})
d={}
for col in df:
    d[col] = df[col].unique()
d

Out[111]:
{'a': array([0, 1, 2, 4], dtype=int64), 'b': array([1, 2], dtype=int64)}
EdChum
la source
est-il possible de vérifier le caractère unique de plusieurs colonnes?
Anoop D
J'ai obtenu la réponse à une autre question SO en utilisant numpynp.unique(df[['column1','column2']].values)
Anoop D
6

Pour résoudre un problème similaire, j'utilise groupby:

print(f"Distinct entries: {len(df.groupby(['col1', 'col2']))}")

Cependant, si cela est approprié dépendra de ce que vous voulez faire avec le résultat (dans mon cas, je voulais juste l'équivalent de COUNT DISTINCTcomme indiqué).

ncoghlan
la source
-1

Vous pouvez prendre les ensembles de colonnes et simplement soustraire le plus petit ensemble du plus grand ensemble:

distinct_values = set(df['a'])-set(df['b'])
Dorante
la source