web-dev-qa-db-fra.com

pandas valeurs uniques colonnes multiples

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'
74
user2333196

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
123
Alex Riley

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)
7
Mike
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

Ou:

set(df.Col1) | set(df.Col2)
5
James Little

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

1
erikreed

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'])
1
Jerome Montino

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)
0
Lisle
np.unique(df.values.flatten())
0
Cohensius

voici une autre façon


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

Le résultat sera ['Mary', 'Joe', 'Steve', 'Bob', 'Bill']

0
smishra