pandas valeurs uniques plusieurs colonnes

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 retourner les valeurs uniques de 'Col1' et 'Col2'?

La sortie souhaitée est

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'
61
demandé sur Alex Riley 2014-11-17 19:21:12

6 réponses

pd.unique renvoie les valeurs uniques d'un tableau d'entrée, ou 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 plus simple est de sélectionner les colonnes que vous voulez, puis d'afficher les valeurs dans un tableau NumPy aplati. Toute 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 pour aplatir le tableau dans l'ordre où les éléments sont stockés en mémoire (les pandas stockent généralement les tableaux sous-jacents dans Fortran-contigu order; colonnes avant les lignes). Cela peut être significatif que d'utiliser l'ordre 'C' par défaut de la méthode.


, Une alternative consiste à sélectionner les colonnes et les passer à 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 ainsi, cela est susceptible 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 des valeurs uniques.

La différence de vitesse est significative pour les DataFrames plus grandes (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
102
répondu Alex Riley 2017-11-11 15:12:44

J'ai configuré un 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 unique function:

>>> pandas.concat([df['a'], df['b']]).unique()
array(['a', 'b', 'd', 'e', 'g', 'h'], dtype=object)
5
répondu Mike 2014-11-17 16:30:18
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

Ou:

set(df.Col1) | set(df.Col2)
4
répondu James Little 2014-11-17 16:31:42

Non-pandas solution: 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)

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
répondu Manhattan 2014-11-17 16:30:14

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)

Ce changement a été introduit en novembre 2016: https://github.com/numpy/numpy/commit/1f764dbff7c496d6636dc0430f083ada9ff4e4be

0
répondu erikreed 2017-08-18 01:56:56

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

df['Col3'] = df[['Col1', 'Col2']].apply(lambda x: ''.join(x), axis=1)
0
répondu Lisle 2018-06-06 20:26:09