2016-02-23 16 views
5

Tôi có một bảng SQL mà tôi có thể đọc trong như một khung dữ liệu Pandas, có cấu trúc sau:Làm cách nào để tạo SparseDataFrame hiệu quả từ một bảng dài?

user_id value 
1   100 
1   200 
2   100 
4   200 

Đó là một đại diện của một ma trận, mà tất cả các giá trị là 1 hoặc 0. dày đặc đại diện của ma trận này sẽ trông như thế này:

100 200 
1 1 1 
2 1 0 
4 0 1 

Thông thường, để làm chuyển đổi này, bạn có thể sử dụng trục, nhưng trong trường hợp của tôi với hàng chục hoặc hàng trăm triệu hàng trong bảng đầu tiên ta có một ma trận dày đặc lớn đầy đủ của số không đắt tiền để kéo xung quanh. Bạn có thể chuyển đổi nó thành thưa thớt, nhưng nhận được rằng đến nay đòi hỏi rất nhiều tài nguyên.

Hiện tại tôi đang làm việc trên một giải pháp để gán số hàng cho mỗi user_id, sắp xếp và sau đó chia cột 'giá trị' thành SparseSeries trước khi kết hợp lại thành SparseDataFrame. Có cách nào tốt hơn?

+0

Tôi chưa thấy nhiều cuộc thảo luận về SparseSeries trên SO. Tôi đã trả lời một số câu hỏi về việc chuyển qua lại giữa điều đó và ma trận 'scipy'' sparse'. Ấn tượng của tôi là cấu trúc Pandas 'sparse' vẫn đang được phát triển. – hpaulj

+0

Tôi đã tìm thấy một số ít, như câu trả lời của bạn ở đây http://stackoverflow.com/questions/34181494/populate-a-pandas-sparsedataframe-from-a-scipy-sparse-coo-matrix Vấn đề là nó không dường như không có quy mô. Ngay bây giờ tôi đang cố gắng chuyển đổi một ma trận csc là 40.000 x 15.000 và nó đã được chạy trong hơn 30 phút. –

Trả lời

1

Tôi đã đến một giải pháp, mặc dù một giải pháp không hoàn hảo.

Điều người ta có thể làm là tạo thủ công từ các cột một số Pandas SparseSeries, kết hợp chúng thành một dict, và sau đó đưa dict đó vào một DataFrame (không phải là SparseDataFrame). Đúc dưới dạng SparseDataFrame hiện đang truy cập một hàm tạo chưa trưởng thành, điều này sẽ giải mã toàn bộ đối tượng thành dày đặc và sau đó trở lại thành dạng thưa thớt bất kể đầu vào. Tuy nhiên, việc xây dựng SparseSeries thành một DataFrame thông thường, duy trì sự thưa thớt nhưng tạo ra một đối tượng DataFrame khả thi và hoàn chỉnh.

Dưới đây là minh chứng về cách thực hiện, viết rõ ràng hơn cho hiệu suất. Một sự khác biệt với việc thực hiện của riêng tôi là tôi đã tạo ra dict của vectơ thưa thớt như một sự hiểu biết dict thay vì một vòng lặp.

import pandas 
import numpy 

df = pandas.DataFrame({'user_id':[1,2,1,4],'value':[100,100,200,200]}) 

# Get unique users and unique features 
num_rows = len(df['user_id'].unique()) 
num_features = len(df['value'].unique()) 
unique_users = df['user_id'].unique().copy() 
unique_features = df['value'].unique().copy() 
unique_users.sort() 
unique_features.sort() 


# assign each user_id to a row_number 
user_lookup = pandas.DataFrame({'uid':range(num_rows), 'user_id':unique_users}) 


vec_dict = {} 

# Create a sparse vector for each feature 
for i in range(num_features): 
    users_with_feature = df[df['value']==unique_features[i]]['user_id'] 

    uid_rows = user_lookup[user_lookup['user_id'].isin(users_with_feature)]['uid'] 

    vec = numpy.zeros(num_rows) 
    vec[uid_rows] = 1 

    sparse_vec = pandas.Series(vec).to_sparse(fill_value=0) 

    vec_dict[unique_features[i]] = sparse_vec 


my_pandas_frame = pandas.DataFrame(vec_dict)  
my_pandas_frame = my_pandas_frame.set_index(user_lookup['user_id']) 

Kết quả:

>>> my_pandas_frame 
     100 200 
user_id   
1   1 1 
2   1 0 
4   0 1 

>>> type(my_pandas_frame) 
<class 'pandas.core.frame.DataFrame'> 

>>> type(my_pandas_frame[100]) 
<class 'pandas.sparse.series.SparseSeries'> 

Hoàn thành, nhưng vẫn còn thưa thớt. Có một vài cảnh báo, nếu bạn làm một bản sao đơn giản hoặc tập hợp con không-tại-chỗ sau đó nó sẽ quên chính nó và cố gắng để recast dày đặc, nhưng đối với mục đích của tôi, tôi khá hài lòng với nó.

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