我学习Spark已有一段时间了,但今天我陷入了困境,我正在使用Audioscrobbler Dataset来创建推荐模型。
我有基于ALS的模型,并根据以下定义提出了建议:
def makeRecommendations(model: ALSModel, userID: Int,howMany: Int): DataFrame = {
val toRecommend = model.itemFactors.select($"id".as("artist")).withColumn("user", lit(userID))
model.transform(toRecommend).
select("artist", "prediction", "user").
orderBy($"prediction".desc).
limit(howMany)
}
它正在生成预期的输出,但是现在我想使用Predictions DF和User Data DF创建一个新的DataFrame列表。
新的DF列表由“ Predictions DF”和“ Listened”中的Predicted值组成,如果用户未收听艺术家,则为0;如果用户未收听,则为1,如下所示:
我尝试了以下解决方案:
val recommendationsSeq = someUsers.map { userID =>
//Gets the artists from user in testData
val artistsOfUser = testData.where($"user".===(userID)).select("artist").rdd.map(r => r(0)).collect.toList
// Recommendations for each user
val recoms = makeRecommendations(model, userID, numRecom)
//Insert a column listened with 1 if the artist in the test set for the user and 0 otherwise
val recomOutput = recoms.withColumn("listened", when($"artist".isin(artistsOfUser: _*), 1.0).otherwise(0.0)).drop("artist")
(recomOutput)
}.toSeq
但是当推荐有30个以上的用户时,这非常耗时。我相信还有更好的方法,
有人可以提出想法吗?
谢谢
答案 0 :(得分:1)
您可以尝试加入数据帧,然后进行goupby计数:
scala> val df1 = Seq((1205,0.9873411,1000019)).toDF("artist","prediction","user")
scala> df1.show()
+------+----------+-------+
|artist|prediction| user|
+------+----------+-------+
| 1205| 0.9873411|1000019|
+------+----------+-------+
scala> val df2 = Seq((1000019,1205,40)).toDF("user","artist","playcount")
scala> df2.show()
+-------+------+---------+
| user|artist|playcount|
+-------+------+---------+
|1000019| 1205| 40|
+-------+------+---------+
scala> df1.join(df2,Seq("artist","user")).groupBy('prediction).count().show()
+----------+-----+
|prediction|count|
+----------+-----+
| 0.9873411| 1|
+----------+-----+