Pandas eindeutige Werte mehrere Spalten

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

Was ist der beste Weg, um die eindeutigen Werte von 'Col1' und 'Col2' zurückzugeben?

Die gewünschte Ausgabe ist

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'
user2333196
quelle
3
Siehe auch eindeutige Wertekombinationen in ausgewählten Spalten im Pandas-Datenrahmen und Anzahl für eine andere, aber verwandte Frage. Die ausgewählte Antwort dort verwendetdf1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Paul Rougieux

Antworten:

198

pd.unique Gibt die eindeutigen Werte aus einem Eingabearray oder einer DataFrame-Spalte oder einem Index zurück.

Die Eingabe für diese Funktion muss eindimensional sein, sodass mehrere Spalten kombiniert werden müssen. Am einfachsten ist es, die gewünschten Spalten auszuwählen und dann die Werte in einem abgeflachten NumPy-Array anzuzeigen. Die ganze Operation sieht so aus:

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

Beachten Sie, dass dies ravel()eine Array-Methode ist, die (wenn möglich) eine Ansicht eines mehrdimensionalen Arrays zurückgibt. Das Argument 'K'weist die Methode an, das Array in der Reihenfolge zu reduzieren, in der die Elemente im Speicher gespeichert sind (Pandas speichert normalerweise zugrunde liegende Arrays in fortlaufender Fortran-Reihenfolge ; Spalten vor Zeilen). Dies kann erheblich schneller sein als bei Verwendung der Standardreihenfolge 'C' der Methode.


Eine alternative Möglichkeit besteht darin, die Spalten auszuwählen und an folgende Adresse zu übergeben np.unique:

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

Hier ist keine Verwendung erforderlich, ravel()da die Methode mehrdimensionale Arrays verarbeitet. Dies ist jedoch wahrscheinlich langsamer als pd.uniquedie Verwendung eines sortierungsbasierten Algorithmus anstelle einer Hashtabelle zur Identifizierung eindeutiger Werte.

Der Geschwindigkeitsunterschied ist bei größeren DataFrames erheblich (insbesondere wenn nur eine Handvoll eindeutiger Werte vorhanden sind):

>>> 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
quelle
2
Wie erhalten Sie einen Datenrahmen anstelle eines Arrays zurück?
Lisle
1
@Lisle: Beide Methoden geben ein NumPy-Array zurück, sodass Sie es manuell erstellen müssen, z pd.DataFrame(unique_values). Es gibt keine gute Möglichkeit, einen DataFrame direkt zurückzugewinnen.
Alex Riley
@Lisle, da er pd.unique verwendet hat, wird eine numpy.ndarray als endgültige Ausgabe zurückgegeben. Haben Sie das gefragt?
Ash Upadhyay
1
@Lisle, vielleicht dieses df = df.drop_duplicates (subset = ['C1', 'C2', 'C3'])?
Tickly Potato
14

Ich habe ein DataFramemit ein paar einfachen Zeichenfolgen in den Spalten eingerichtet:

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

Sie können die Spalten, an denen Sie interessiert sind, verketten und die uniqueFunktion aufrufen :

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

Oder:

set(df.Col1) | set(df.Col2)
James Little
quelle
1

Nichtlösung pandas: mit 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)

Ausgabe:

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

Für diejenigen von uns, die alles lieben, Pandas, gelten und natürlich Lambda-Funktionen:

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

Hier ist ein anderer Weg


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

Die Ausgabe wird ['Mary', 'Joe', 'Steve', 'Bob', 'Bill'] sein.

Smishra
quelle