df = pd.DataFrame({'Col1': ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'],
'Col2': ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'],
'Col3': np.random.random(5)})
Quel est le meilleur moyen de renvoyer les valeurs uniques de 'Col1' et de 'Col2'?
La sortie souhaitée est
'Bob', 'Joe', 'Bill', 'Mary', 'Steve'
pd.unique
renvoie les valeurs uniques d'un tableau d'entrée, d'une colonne ou d'un index DataFrame.
L'entrée pour cette fonction doit être unidimensionnelle, donc plusieurs colonnes devront être combinées. La méthode la 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 que ravel()
est 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 un ordre Fortran-contigu ; colonnes avant les lignes). Cela peut être beaucoup plus rapide que d'utiliser l'ordre 'C' par défaut 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 risque d'être plus lent que pd.unique
car il utilise un algorithme basé sur le tri plutôt qu'une table de hachage pour identifier les valeurs uniques.
La différence de vitesse est significative pour les grands DataFrames (surtout s’il n’ya que quelques 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
J'ai configuré une DataFrame
avec 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 fonction unique
:
>>> pandas.concat([df['a'], df['b']]).unique()
array(['a', 'b', 'd', 'e', 'g', 'h'], dtype=object)
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}
Ou:
set(df.Col1) | set(df.Col2)
Une solution mise à jour utilisant numpy v1.13 + nécessite de spécifier l'axe dans np.unique si vous utilisez plusieurs colonnes, sinon le tableau est implicitement aplati.
import numpy as np
np.unique(df[['col1', 'col2']], axis=0)
Cette modification a été introduite en novembre 2016: https://github.com/numpy/numpy/commit/1f764dbff7c496d6636dc0430f083ada9ff4e4be
Solution non -pandas
: utilisation de 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)
Sortie:
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'])
pour ceux d'entre nous qui aiment tout ce qui concerne les pandas, appliquez et bien sûr les fonctions lambda:
df['Col3'] = df[['Col1', 'Col2']].apply(lambda x: ''.join(x), axis=1)
np.unique(df.values.flatten())
voici une autre façon
import numpy as np
set(np.concatenate(df.values))
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))
Le résultat sera ['Mary', 'Joe', 'Steve', 'Bob', 'Bill']