pandas valeurs uniques plusieurs colonnes

134
df = pd.DataFrame({'Col1': ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
                   'Col2': ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
                   'Col3': np.random.random(5)})

Quelle est la meilleure façon de renvoyer les valeurs uniques de «Col1» et «Col2»?

La sortie souhaitée est

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'
user2333196
la source
3
Voir également les combinaisons uniques de valeurs dans les colonnes sélectionnées dans le cadre de données pandas et compter pour une question différente mais connexe. La réponse choisie ici utilisedf1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Paul Rougieux

Réponses:

198

pd.unique renvoie les valeurs uniques d'un tableau d'entrée, d'une colonne ou d'un index DataFrame.

L'entrée de cette fonction doit être unidimensionnelle, de sorte que plusieurs colonnes devront être combinées. Le moyen le plus simple consiste à sélectionner les colonnes souhaitées, puis à afficher les valeurs dans un tableau NumPy aplati. L'ensemble de l'opération ressemble à ceci:

>>> pd.unique(df[['Col1', 'Col2']].values.ravel('K'))
array(['Bob', 'Joe', 'Bill', 'Mary', 'Steve'], dtype=object)

Notez qu'il ravel()s'agit d'une méthode de tableau qui renvoie une vue (si possible) d'un tableau multidimensionnel. L'argument 'K'indique à la méthode d'aplatir le tableau dans l'ordre dans lequel les éléments sont stockés en mémoire (les pandas stockent généralement les tableaux sous-jacents dans l' ordre contigu à Fortran ; les colonnes avant les lignes). Cela peut être beaucoup plus rapide que d'utiliser l'ordre par défaut «C» de la méthode.


Une autre méthode consiste à sélectionner les colonnes et à les transmettre à np.unique:

>>> np.unique(df[['Col1', 'Col2']].values)
array(['Bill', 'Bob', 'Joe', 'Mary', 'Steve'], dtype=object)

Il n'est pas nécessaire d'utiliser ravel()ici car la méthode gère les tableaux multidimensionnels. Même dans ce cas, cela sera probablement plus lent que pd.uniquecar il utilise un algorithme basé sur le tri plutôt qu'une table de hachage pour identifier des valeurs uniques.

La différence de vitesse est significative pour les DataFrames plus volumineux (surtout s'il n'y a qu'une poignée de valeurs uniques):

>>> df1 = pd.concat([df]*100000, ignore_index=True) # DataFrame with 500000 rows
>>> %timeit np.unique(df1[['Col1', 'Col2']].values)
1 loop, best of 3: 1.12 s per loop

>>> %timeit pd.unique(df1[['Col1', 'Col2']].values.ravel('K'))
10 loops, best of 3: 38.9 ms per loop

>>> %timeit pd.unique(df1[['Col1', 'Col2']].values.ravel()) # ravel using C order
10 loops, best of 3: 49.9 ms per loop
Alex Riley
la source
2
Comment récupérer un dataframe au lieu d'un tableau?
Lisle
1
@Lisle: les deux méthodes renvoient un tableau NumPy, vous devrez donc le construire manuellement, par exemple pd.DataFrame(unique_values). Il n'y a pas de bon moyen de récupérer directement un DataFrame.
Alex Riley
@Lisle depuis qu'il a utilisé pd.unique il renvoie un numpy.ndarray en sortie finale. Est-ce ce que vous demandiez?
Ash Upadhyay
1
@Lisle, peut-être celui-ci df = df.drop_duplicates (subset = ['C1', 'C2', 'C3'])?
patate tickly le
14

J'ai configuré un DataFrameavec quelques chaînes simples dans ses colonnes:

>>> df
   a  b
0  a  g
1  b  h
2  d  a
3  e  e

Vous pouvez concaténer les colonnes qui vous intéressent et appeler la uniquefonction:

>>> pandas.concat([df['a'], df['b']]).unique()
array(['a', 'b', 'd', 'e', 'g', 'h'], dtype=object)
Mike
la source
7
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

Ou:

set(df.Col1) | set(df.Col2)
James Little
la source
1

Non- pandassolution: en utilisant set ().

import pandas as pd
import numpy as np

df = pd.DataFrame({'Col1' : ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
              'Col2' : ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
               'Col3' : np.random.random(5)})

print df

print set(df.Col1.append(df.Col2).values)

Production:

   Col1   Col2      Col3
0   Bob    Joe  0.201079
1   Joe  Steve  0.703279
2  Bill    Bob  0.722724
3  Mary    Bob  0.093912
4   Joe  Steve  0.766027
set(['Steve', 'Bob', 'Bill', 'Joe', 'Mary'])
NullDev
la source
1

pour ceux d'entre nous qui aiment toutes les choses pandas, appliquent et bien sûr les fonctions lambda:

df['Col3'] = df[['Col1', 'Col2']].apply(lambda x: ''.join(x), axis=1)
Lisle
la source
1

voici une autre façon


import numpy as np
set(np.concatenate(df.values))
muon
la source
0
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))

La sortie sera ['Mary', 'Joe', 'Steve', 'Bob', 'Bill']

Smishra
la source