Pandas 使用pyspark将用户项目评级列表转换为用户项目矩阵
这就是用户项目分级列表作为数据框的外观Pandas 使用pyspark将用户项目评级列表转换为用户项目矩阵,pandas,apache-spark,pyspark,apache-spark-sql,pyspark-sql,Pandas,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Sql,这就是用户项目分级列表作为数据框的外观 item_id rating user_id 0 aaaaaaa 5 X 1 bbbbbbb 2 Y 2 ccccccc 5 Z 3 ddddddd 1 T from pyspark.sql.functions import first df.groupby('user_id') \ .pivot('item_id') \ .agg(
item_id rating user_id
0 aaaaaaa 5 X
1 bbbbbbb 2 Y
2 ccccccc 5 Z
3 ddddddd 1 T
from pyspark.sql.functions import first
df.groupby('user_id') \
.pivot('item_id') \
.agg(first('rating'))
这就是我在pandas中创建用户项矩阵的方法,使用真实数据集(大约500k行)只需几秒钟:
我正在尝试这种方法来实现与pyspark dataframe相同的结果
item_id rating user_id
0 aaaaaaa 5 X
1 bbbbbbb 2 Y
2 ccccccc 5 Z
3 ddddddd 1 T
from pyspark.sql.functions import first
df.groupby('user_id') \
.pivot('item_id') \
.agg(first('rating'))
但要用真实的数据完成这项工作需要很多时间。有没有更聪明/更快的方法来实现这一点?基本上,我正在尝试从用户项目评级列表构建用户项目矩阵。这是一种基于RDD的替代方法
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|
+---+----+----+----+----+----+
现在我假设一个用户可能会对多个项目进行评分。在这种情况下,您可能需要根据用户id减少RDD并合并评级。它只是在.toDF之前的一个reduceByKey语句,您应该得到这样一个df。这是一种基于RDD的替代方法
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|
+---+----+----+----+----+----+
现在我假设一个用户可能会对多个项目进行评分。在这种情况下,您可能需要根据用户id减少RDD并合并评级。这只是前面的一个reduceByKey语句。toDF,你应该得到这样一个df。我希望它能起作用:(我希望它能起作用:(必须有一种更简洁的方法来做到这一点。特别是推荐系统和矩阵分解方法需要实现这一效果。我可以想象一种更精简的方法确实存在。而且,这会引发一个错误;python或至少google colab,看不到
lamba(item,rat,uid)
可以接受。@mjake取决于python版本。在撰写本文时,它使用的是python 2.7或python 3.1或其他不记得的工具。您可以轻松地将其更改为(lambda数据:数据[0]、数据[1]、数据[2])而且应该可以很好地工作!@mjake这个问题是2年前提出来的。从那时起,pyspark已经发展起来,你有了诸如explode和其他功能……你可以对此进行探索。现在肯定有一种简单的方法可以用数据帧来做这件事。必须有一种更简洁的方法来做这件事。推荐系统和矩阵分解方法,特别是,n我想一个更精简的方法确实存在。而且,这会抛出一个错误;python或者至少google colab,没有看到lamba(item,rat,uid)
可以接受。@mjake取决于python版本。在撰写本文时,它使用的是python 2.7或python 3.1或其他不记得的工具。您可以轻松地将其更改为(lambda数据:数据[0]、数据[1]、数据[2])而且应该可以很好地工作!@mjake这个问题是2年前提出的。从那时起,pyspark已经发展起来,您可以使用explode和其他功能……您可以对此进行探索。现在肯定有一种简单的方法可以使用数据帧来实现这一点。