2016-08-03 24 views
12

Cho một ma trận từ một SFrame:cách hiệu quả để có được những giá trị độc đáo từ 2 hay nhiều cột trong một Dataframe

>>> from sframe import SFrame 
>>> sf =SFrame({'x':[1,1,2,5,7], 'y':[2,4,6,8,2], 'z':[2,5,8,6,2]}) 
>>> sf 
Columns: 
    x int 
    y int 
    z int 

Rows: 5 

Data: 
+---+---+---+ 
| x | y | z | 
+---+---+---+ 
| 1 | 2 | 2 | 
| 1 | 4 | 5 | 
| 2 | 6 | 8 | 
| 5 | 8 | 6 | 
| 7 | 2 | 2 | 
+---+---+---+ 
[5 rows x 3 columns] 

Tôi muốn nhận được những giá trị độc đáo cho các cột xy và tôi có thể làm điều đó như vậy:

>>> sf['x'].unique().append(sf['y'].unique()).unique() 
dtype: int 
Rows: 7 
[2, 8, 5, 4, 1, 7, 6] 

Bằng cách này tôi nhận được giá trị duy nhất của x và giá trị duy nhất của y, sau đó nối chúng và nhận giá trị duy nhất của danh sách nối.

tôi cũng có thể làm điều đó như thế:

>>> sf['x'].append(sf['y']).unique() 
dtype: int 
Rows: 7 
[2, 8, 5, 4, 1, 7, 6] 

Nhưng theo cách đó, nếu x của tôi và cột y là rất lớn với rất nhiều bản sao, tôi sẽ phụ thêm nó vào một container rất lớn trước khi nhận độc đáo .

Có cách nào hiệu quả hơn để lấy giá trị duy nhất của cột được tạo từ 2 cột trở lên trong khung nội tuyến không?

Tương đương với gấu trúc theo cách hiệu quả để nhận giá trị duy nhất từ ​​2 cột trở lên trong pandas là gì?

+0

Thứ tự xuất phát từ vật chất đầu ra có quan trọng không? Nó sẽ được okay để có đầu ra như là một danh sách hoặc một mảng? – Divakar

+0

[API của SFrame] (https://turi.com/products/create/docs/generated/graphlab.SFrame.html) khá kém so với API Pandas, vì vậy tôi không nghĩ bạn có thể làm điều đó trong nhiều hơn nữa cách hiệu quả so với các giải pháp của bạn. Có lẽ đã đến lúc cân nhắc việc sử dụng [Apache Spark] (http://spark.apache.org/)? – MaxU

Trả lời

2

Tôi không có SFrame nhưng thử nghiệm trên pd.DataFrame:

sf[["x", "y"]].stack().value_counts().index.tolist() 
    [2, 1, 8, 7, 6, 5, 4] 
+0

Câu hỏi nhanh, trong trường hợp này, một cột (có bản sao) được nối vào một cột khác (có bản sao) trước khi thực hiện '.value_counts()' đúng không? – alvas

+0

Có, mã ngăn xếp dữ liệu, để truy cập các giá trị cơ bản. – Merlin

+0

Nó hoạt động, tôi đã upvoted. Nhưng tôi nghĩ rằng một câu trả lời sframe sẽ thích hợp hơn. Hy vọng bạn không nhớ =) – alvas

1

Mặc dù tôi không biết làm thế nào để làm điều đó trong SFrame, đây là một lời giải thích dài @ câu trả lời Merlin của:

>>> import pandas as pd 
>>> df = pd.DataFrame({'x':[1,1,2,5,7], 'y':[2,4,6,8,2], 'z':[2,5,8,6,2]}) 
>>> df[['x', 'y']] 
    x y 
0 1 2 
1 1 4 
2 2 6 
3 5 8 
4 7 2 

Để trích xuất chỉ cột X và Y

>>> df[['x', 'y']] # Extract only columns x and y 
    x y 
0 1 2 
1 1 4 
2 2 6 
3 5 8 
4 7 2 

Để ngăn xếp 2 cột cho mỗi hàng vào 1 đồng hàng lumn, trong khi vẫn có thể truy cập chúng như một cuốn từ điển:

>>> df[['x', 'y']].stack()      
0 x 1 
    y 2 
1 x 1 
    y 4 
2 x 2 
    y 6 
3 x 5 
    y 8 
4 x 7 
    y 2 
dtype: int64 
>>> df[['x', 'y']].stack()[0]  
x 1 
y 2 
dtype: int64 
>>> df[['x', 'y']].stack()[0]['x'] 
1 
>>> df[['x', 'y']].stack()[0]['y'] 
2 

Đếm các giá trị cá nhân của tất cả các yếu tố trong cột kết hợp:

>>> df[['x', 'y']].stack().value_counts() # index(i.e. keys)=elements, Value=counts 
2 3 
1 2 
8 1 
7 1 
6 1 
5 1 
4 1 

Để truy cập vào các chỉ số và đếm:

>>> df[['x', 'y']].stack().value_counts().index  
Int64Index([2, 1, 8, 7, 6, 5, 4], dtype='int64') 
>>> df[['x', 'y']].stack().value_counts().values 
array([3, 2, 1, 1, 1, 1, 1]) 

Chuyển đổi thành danh sách:

>>> sf[["x", "y"]].stack().value_counts().index.tolist() 
[2, 1, 8, 7, 6, 5, 4] 

Vẫn là một câu trả lời SFrame cũng sẽ tuyệt vời. Cú pháp tương tự không hoạt động đối với SFrame.

+0

IIUC, 'stack()' rất có thể sẽ sao chép dữ liệu cơ bản - có thể là điều bạn muốn tránh. – ptrj

2

Cách đơn giản nhất tôi có thể nghĩ là để chuyển đổi sang một mảng NumPy sau đó tìm giá trị duy nhất

np.unique(sf[['x', 'y']].to_numpy()) 

array([1, 2, 4, 5, 6, 7, 8]) 

Nếu bạn cần nó trong một sframe

SFrame({'xy_unique': np.unique(sf[['x', 'y']].to_numpy())}) 

enter image description here

2

SFrame

Tôi chưa sử dụng SFrame và không biết điều kiện nào nó sao chép dữ liệu. (Chọn sf['x'] hoặc append sao chép dữ liệu vào bộ nhớ?). Có pack_columnsstack phương pháp trong SFrame và nếu họ không sao chép dữ liệu, sau này nên làm việc:

sf[['x', 'y']].pack_columns(new_column_name='N').stack('N').unique() 

gấu trúc

Nếu dữ liệu của bạn phù hợp với bộ nhớ thì có thể bạn có thể làm điều đó trong gấu trúc hiệu quả mà không cần sao chép thêm.

# copies the data to memory 
df = sf[['x', 'y']].to_dataframe() 

# a reference to the underlying numpy array (no copy) 
vals = df.values 

# 1d array: 
# (numpy.ravel doesn't copy if it doesn't have to - it depends on the data layout) 
if np.isfortran(vals): 
    vals_1d = vals.ravel(order='F') 
else: 
    vals_1d = vals.ravel(order='C') 

uniques = pd.unique(vals_1d) 

gấu trúc của unique là hiệu quả hơn NumPy của np.unique bởi vì nó không sắp xếp.

2

Hãy xem this answer cho một câu hỏi tương tự. Lưu ý rằng chức năng của Pandas 'pd.unique nhanh hơn đáng kể so với Numpy's.

>>> pd.unique(sf[['x','y']].values.ravel()) 
array([2, 8, 5, 4, 1, 7, 6], dtype=object) 
1

Dưới đây là một chút điểm chuẩn giữa ba phương pháp có thể:

from sframe import SFrame 
import numpy as np 
import pandas as pd 
import timeit 

sf = SFrame({'x': [1, 1, 2, 5, 7], 'y': [2, 4, 6, 8, 2], 'z': [2, 5, 8, 6, 2]}) 


def f1(sf): 
    return sf['x'].unique().append(sf['y'].unique()).unique() 


def f2(sf): 
    return sf['x'].append(sf['y']).unique() 


def f3(sf): 
    return np.unique(sf[['x', 'y']].to_numpy()) 

N = 1000 

print timeit.timeit('f1(sf)', setup='from __main__ import f1, sf', number=N) 
print timeit.timeit('f2(sf)', setup='from __main__ import f2, sf', number=N) 
print timeit.timeit('f3(sf)', setup='from __main__ import f3, sf', number=N) 

# 13.3195129933 
# 4.66225642657 
# 3.65669089489 
# [Finished in 23.6s] 

Benchmark sử dụng python2.7.11 x64 trên windows7 + i7_2.6ghz

Kết luận: Tôi muốn đề nghị bạn sử dụng np.unique, đó là về cơ bản f3.

Các vấn đề liên quan