2014-11-17 50 views
45
df = pd.DataFrame({'Col1': ['Bob', 'Joe', 'Bill', 'Mary', 'Joe'], 
        'Col2': ['Joe', 'Steve', 'Bob', 'Bob', 'Steve'], 
        'Col3': np.random.random(5)}) 

Cách tốt nhất để trả lại giá trị duy nhất của 'Col1' và 'Col2' là gì?gấu trúc giá trị duy nhất nhiều cột

Kết quả mong muốn là

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

Trả lời

77

pd.unique trả về giá trị duy nhất từ ​​một mảng đầu vào, hoặc cột DataFrame hoặc chỉ số.

Đầu vào cho hàm này cần phải là một chiều, do đó, nhiều cột sẽ cần phải được kết hợp. Cách đơn giản nhất là chọn các cột bạn muốn và sau đó xem các giá trị trong một mảng NumPy phẳng. Toàn bộ hoạt động trông như thế này:

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

Lưu ý rằng ravel() là một phương pháp mảng hơn việc quay lại một cái nhìn (nếu có thể) của một mảng đa chiều. Đối số 'K' cho phương thức làm phẳng mảng theo thứ tự các phần tử được lưu trữ trong bộ nhớ (gấu trúc thường lưu trữ các mảng cơ bản trong Fortran-contiguous order; cột trước hàng). Điều này có thể đáng kể so với việc sử dụng thứ tự 'C' mặc định của phương thức.


Một cách khác là để chọn các cột và vượt qua chúng để np.unique:

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

Không có nhu cầu sử dụng ravel() ở đây là phương pháp xử lý mảng đa chiều. Mặc dù vậy, điều này có thể chậm hơn pd.unique vì nó sử dụng một thuật toán dựa trên phân loại chứ không phải là một hashtable để xác định các giá trị duy nhất.

Sự khác biệt về tốc độ là quan trọng đối với DataFrames lớn hơn (đặc biệt là nếu chỉ có một số ít các giá trị duy nhất):

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

Các '.các giá trị' trong câu trả lời trước của bạn là bắt buộc; nếu không nó sẽ trả về 'mảng (['Col1', 'Col2'], dtype = '| S4')' – congusbongus

+0

@congusbongus: cảm ơn vì đã chỉ ra điều đó - tôi đã cập nhật câu trả lời. Có vẻ như '.values' là cần thiết cho một số phiên bản của Pandas/NumPy (tôi đã thử nghiệm điều này với NumPy 1.9.2 và Pandas 15.2 và nó hoạt động mà không có). –

+1

Làm thế nào để bạn lấy lại một khung dữ liệu thay vì một mảng? – Lisle

1

phi pandas giải pháp: sử dụng 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) 

Output:

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']) 
4

tôi đã thiết lập một DataFrame một số loại dây đơn giản trong các cột của nó:

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

Bạn có thể ghép các cột mà bạn đang quan tâm và gọi unique chức năng :

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

Hoặc:

set(df.Col1) | set(df.Col2) 
Các vấn đề liên quan