2017-06-16 10 views
0

So sieht die user-item-rating list wie ein Pandas Datenframe aus.Benutzer-Item-Bewertungsliste in user-item-matrix mit pyspark umwandeln

item_id rating user_id 
0 aaaaaaa  5  X 
1 bbbbbbb  2  Y 
2 ccccccc  5  Z 
3 ddddddd  1  T 

Dies, wie ich erstelle Benutzer-item-Matrix in Pandas und es dauert nur ein paar Sekunden, mit realer Datenmenge (ca. 500k Reihe):

user_item_matrix = df.pivot(index = 'user_id', columns ='item_id', values = 'rating') 

item_id aaaaaaa bbbbbbb ccccccc ddddddd 
user_id          
T   NaN  NaN  NaN  1.0 
X   5.0  NaN  NaN  NaN 
Y   NaN  2.0  NaN  NaN 
Z   NaN  NaN  5.0  NaN 

ich diesen Ansatz versuche gleiche zu erreichen Ergebnis mit Pyspark-Datenrahmen.

from pyspark.sql.functions import first 

df.groupby('user_id') \ 
    .pivot('item_id') \ 
    .agg(first('rating')) 

Aber es dauert Ewigkeiten mit echten Daten zu vervollständigen. Gibt es einen klüger/schnelleren Weg, dies zu erreichen? Grundsätzlich versuche ich eine User-Item-Matrix aus einer User-Item-Rating-Liste aufzubauen.

+0

Ich hätte erwartet, dass das funktioniert :( – muon

Antwort

0

Dies ist ein alternativer Ansatz, der auf RDD basiert.

rating_list = [['aaa',5.0,'T'],['bbb',5.0,'U'],['ccc',5.0,'V'],['ddd',5.0,'W'],['eee',5.0,'X']] 
df = sc.parallelize(rating_list).toDF(['item_id','rating','user_id']) 
df.show() 

+-------+------+-------+ 
|item_id|rating|user_id| 
+-------+------+-------+ 
| aaa| 5.0|  T| 
| bbb| 5.0|  U| 
| ccc| 5.0|  V| 
| ddd| 5.0|  W| 
| eee| 5.0|  X| 
+-------+------+-------+ 


items = df.select('item_id').rdd.map(lambda data:data.item_id).collect() 
item_len = len(items) 

def transformRating(item_id,rating,user_id): 
    rating_list = [rating if ele == item_id else None for ele in items] 
    return ([user_id]+rating_list) 

df1 = (df.rdd.map(lambda data:(data.item_id,data.rating,data.user_id)) 
      .map(lambda (item,rat,uid):transformRating(item,rat,uid)) 
      .toDF(['uid']+items)) 

df1.show() 

+---+----+----+----+----+----+ 
|uid| aaa| bbb| ccc| ddd| eee| 
+---+----+----+----+----+----+ 
| T| 5.0|null|null|null|null| 
| U|null| 5.0|null|null|null| 
| V|null|null| 5.0|null|null| 
| W|null|null|null| 5.0|null| 
| X|null|null|null|null| 5.0| 
+---+----+----+----+----+----+ 

Jetzt würde ich davon ausgehen, dass ein Benutzer mehrere Elemente bewerten könnte. In diesem Fall müssen Sie möglicherweise die RDD basierend auf user_id und combination rating reduzieren. Es wird nur noch eine reduceByKey-Anweisung vor .toDF geben und Sie sollten ein df so bekommen.