pandy unikalne wartości wielu kolumn

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

Jaki jest najlepszy sposób na zwrócenie unikatowych wartości „Col1” i „Col2”?

Żądane wyjście to

'Bob', 'Joe', 'Bill', 'Mary', 'Steve'
user2333196
źródło
4
Zobacz także unikalne kombinacje wartości w wybranych kolumnach w ramce danych pandy i policz dla innego, ale powiązanego pytania. Wybrana odpowiedź tam używadf1.groupby(['A','B']).size().reset_index().rename(columns={0:'count'})
Paul Rougieux

Odpowiedzi:

212

pd.unique zwraca unikatowe wartości z tablicy wejściowej lub kolumny lub indeksu DataFrame.

Dane wejściowe tej funkcji muszą być jednowymiarowe, więc trzeba będzie połączyć wiele kolumn. Najprostszym sposobem jest wybranie żądanych kolumn, a następnie wyświetlenie wartości w spłaszczonej tablicy NumPy. Cała operacja wygląda tak:

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

Zauważ, że ravel()jest to metoda tablicowa, która zwraca widok (jeśli to możliwe) tablicy wielowymiarowej. Argument 'K'mówi metodzie, aby spłaszczyła tablicę w kolejności, w jakiej elementy są przechowywane w pamięci (pandy zazwyczaj przechowują podstawowe tablice w kolejności ciągłej w języku Fortran ; kolumny przed wierszami). Może to być znacznie szybsze niż użycie domyślnej kolejności „C” metody.


Alternatywnym sposobem jest wybranie kolumn i przekazanie ich do np.unique:

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

Nie ma potrzeby używania ravel()tutaj, ponieważ metoda obsługuje tablice wielowymiarowe. Mimo to prawdopodobnie będzie to wolniejsze niż pd.uniquew przypadku użycia algorytmu opartego na sortowaniu zamiast tablicy hashy do identyfikacji unikalnych wartości.

Różnica w szybkości jest znacząca w przypadku większych ramek DataFrame (zwłaszcza jeśli istnieje tylko kilka unikalnych wartości):

>>> 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
źródło
2
Jak odzyskać ramkę danych zamiast tablicy?
Lisle
1
@Lisle: obie metody zwracają tablicę NumPy, więc będziesz musiał utworzyć ją ręcznie, np pd.DataFrame(unique_values). Nie ma dobrego sposobu na bezpośrednie odzyskanie ramki DataFrame.
Alex Riley
@Lisle, odkąd użył pd.unique, zwraca numpy.ndarray jako końcowe wyjście. Czy o to pytałeś?
Ash Upadhyay,
1
@Lisle, może ten df = df.drop_duplicates (podzbiór = ['C1', 'C2', 'C3'])?
łaskotanie ziemniaków
14

Skonfigurowałem a DataFramez kilkoma prostymi ciągami w jego kolumnach:

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

Możesz konkatenować interesujące Cię kolumny i wywołać uniquefunkcję:

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

Lub:

set(df.Col1) | set(df.Col2)
James Little
źródło
1

Brak pandasrozwiązania: użycie 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)

Wynik:

   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
źródło
1

dla tych z nas, którzy kochają wszystko, co pandy, zastosuj i oczywiście funkcje lambda:

df['Col3'] = df[['Col1', 'Col2']].apply(lambda x: ''.join(x), axis=1)
Lisle
źródło
1

oto inny sposób


import numpy as np
set(np.concatenate(df.values))
mion
źródło
0
list(set(df[['Col1', 'Col2']].as_matrix().reshape((1,-1)).tolist()[0]))

Dane wyjściowe to [„Mary”, „Joe”, „Steve”, „Bob”, „Bill”]

smishra
źródło