我想计算哪个用户查看哪个类别的频率。我是 Spark 和 Python 的新手。这是演示数据:
dataSource = sc.parallelize( [("user1", "film"), ("user1", "film"), ("user2", "film"), ("user2", "books"), ("user2", "books")] )
我通过关键用户减少了这一点并收集了所有类别。然后我分手了以后算了:
dataReduced = dataSource.reduceByKey(lambda x,y : x + "," + y)
catSplitted = dataReduced.map(lambda (user,values) : (values.split(","),user))
每个用户的输出格式如下所示 - > ([cat1,cat1,cat2,catn],用户)
有人可以告诉我如何使用 Spark 和 Python 计算类别,或者您有不同的方法来解决此问题?
答案 0 :(得分:1)
现在我得到了我期望的结果。但我想像我一样连接密钥并不是有利的。也许有人有其他解决方案或任何建议?
# count the categorie views per user
# data
dataSource = sc.parallelize( [("user1", "film"), ("user1", "film"), ("user2", "film"), ("user2", "books"), ("user2", "books")] )
# Create Key,Value | concatenate user and category as key
dataKeyValue = dataSource.map(lambda (user,category) : (user+","+category, 1))
# reduce
dataReduced = dataKeyValue.reduceByKey(lambda x,y : x + y)
# result => [('user2,books', 2), ('user1,film', 2), ('user2,film', 1)]
# split key
cleanResult = dataReduced.map(lambda (key,value) : (key.split(","),value))
答案 1 :(得分:0)
纯粹的python:
ds = [('user1',['film','film','books']), ('user2',['film','books','books'])]
ds1 = map(lambda (x,y):(x,tuple(set((z,y.count(z)) for z in y))),ds)
print ds1
返回:
[('user1', (('film', 2), ('books', 1))), ('user2', (('film', 1), ('books', 2)))]
在火花中,它应该如下(不确定,因为我现在没有获得火花):
dataReduced = dataSource.reduceByKey(lambda x,y : x + "," + y)
catSplitted = dataReduced.map(lambda (user,values) : (user, values.split(","))
catCounted = catSplitted.map(lambda (x,y):(x,tuple(set((z,y.count(z)) for z in y)))
希望这会有所帮助。如果没有,您可以尝试使用spark命令检查如何获取python功能。基本逻辑应该有效
答案 2 :(得分:0)
另一个(更有效且易于阅读的IMO)。 高效,因为SPARK DAG不需要在基于用户的分区后收集重新分区类别,并且因为它使用数据帧而不是RDD,因此易于用户使用。
首先,根据用户和类别制作一个哈希列:
import pyspark.sql.functions as F
df = spark.createDataFrame([("u1", "f"), ("u1", "f"), ("u2", "f"), ("u2", "b"), ("u2", "b")], schema=['u', 'c'])
df = df.withColumn('hash', f.hash())
其次,我们按哈希进行分区,并在本地聚合:
from pyspark.sql import Window
win = Window.partitionBy('hash')
df.withColumns('count', F.count('hash').over(win)).distinct().show()