Panda valori univoci più colonne


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

Qual è il modo migliore per restituire i valori univoci di "Col1" e "Col2"?

L'output desiderato è

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'

3
Vedi anche combinazioni uniche di valori nelle colonne selezionate nel frame di dati Panda e conta per una domanda diversa ma correlata. La risposta selezionata lì utilizzadf1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Paul Rougieux,

Risposte:


198

pd.unique restituisce i valori univoci da un array di input o da una colonna o un indice DataFrame.

L'input per questa funzione deve essere monodimensionale, quindi è necessario combinare più colonne. Il modo più semplice è selezionare le colonne desiderate e quindi visualizzare i valori in un array NumPy appiattito. L'intera operazione è simile a questa:

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

Si noti che ravel()è un metodo array che restituisce una vista (se possibile) di un array multidimensionale. L'argomento 'K'dice al metodo di appiattire l'array nell'ordine in cui gli elementi sono memorizzati (i panda in genere memorizzano gli array sottostanti in ordine Fortran-contiguo ; colonne prima delle righe). Questo può essere significativamente più veloce rispetto all'utilizzo dell'ordine 'C' predefinito del metodo.


Un modo alternativo è selezionare le colonne e passarle a np.unique:

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

Non è necessario utilizzarlo ravel()qui poiché il metodo gestisce array multidimensionali. Anche così, questo sarà probabilmente più lento dipd.unique a quando utilizza un algoritmo basato sull'ordinamento anziché una tabella hash per identificare valori univoci.

La differenza di velocità è significativa per DataFrame più grandi (specialmente se ci sono solo una manciata di valori univoci):

>>> 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

2
Come si ottiene indietro un frame di dati anziché un array?
Lisle,

1
@Lisle: entrambi i metodi restituiscono un array NumPy, quindi dovrai costruirlo manualmente, ad es pd.DataFrame(unique_values). Non c'è un buon modo per recuperare direttamente un DataFrame.
Alex Riley,

@Lisle da quando ha usato pd.unique restituisce un numpy.ndarray come output finale. È questo quello che stavi chiedendo?
Ash Upadhyay,

1
@Lisle, forse questo df = df.drop_duplicates (sottoinsieme = ['C1', 'C2', 'C3'])?
tickly potato

14

Ho installato un DataFramecon alcune semplici stringhe nelle sue colonne:

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

Puoi concatenare le colonne che ti interessano e chiamare la uniquefunzione:

>>> pandas.concat([df['a'], df['b']]).unique()
array(['a', 'b', 'd', 'e', 'g', 'h'], dtype=object)

7
In [5]: set(df.Col1).union(set(df.Col2))
Out[5]: {'Bill', 'Bob', 'Joe', 'Mary', 'Steve'}

O:

set(df.Col1) | set(df.Col2)


1

Non pandassoluzione: usando 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)

Produzione:

   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

per quelli di noi che amano tutte le cose i panda, si applicano e ovviamente le funzioni lambda:

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

1

ecco un altro modo


import numpy as np
set(np.concatenate(df.values))

0
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))

L'output sarà ['Mary', 'Joe', 'Steve', 'Bob', 'Bill']

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.