如何使用DataFrame在Spark中构建CoordinateMatrix?

时间:2017-06-28 12:57:07

标签: pyspark spark-dataframe apache-spark-mllib collaborative-filtering

我正在尝试将ALS算法的Spark实现用于推荐系统,因此我将下面描述的DataFrame构建为训练数据:

|--------------|--------------|--------------|
|    userId    |    itemId    |    rating    |
|--------------|--------------|--------------|

现在,我想创建一个稀疏矩阵,来表示每个用户和每个项目之间的交互。矩阵将是稀疏的,因为如果用户和项之间没有交互,则矩阵中的对应值将为零。因此,最后,大多数值将为零。

但是如何使用CoordinateMatrix实现这一目标?我说的是CoordinateMatrix,因为我正在使用Spark 2.1.1,使用python,在文档中,我看到只有当矩阵的两个维度都很大且矩阵非常稀疏时才应该使用CoordinateMatrix。

换句话说,我如何从这个DataFrame到达CoordinateMatrix,其中行将是用户,列将是项目,而评级将是矩阵中的值?

2 个答案:

答案 0 :(得分:3)

CoordinateMatrix只是MatrixEntrys RDD的包装器。 MatrixEntry只是一个(long,long,float)元组的包装器。 Pyspark允许您从这些元组的RDD创建CoordinateMatrix。如果userIditemId字段都是IntegerTypes而rating类似于FloatType,那么创建所需的矩阵非常简单。

from pyspark.mllib.linalg.distributed import CoordinateMatrix

cmat=CoordinateMatrix(df.rdd.map(tuple))

如果您拥有userIditemId字段的StringTypes,则会稍微复杂一些。您需要首先索引这些字符串,然后将索引传递给CoordinateMatrix。

答案 1 :(得分:1)

使用Spark 2.4.0,我将展示希望满足您需求的整个示例。 使用字典和熊猫创建数据框:

my_dict = {
    'userId': [1,2,3,4,5,6],
    'itemId': [101,102,103,104,105,106],
    'rating': [5.7, 8.8, 7.9, 9.1, 6.6, 8.3]
}
import pandas as pd
pd_df = pd.DataFrame(my_dict)
df = spark.createDataFrame(pd_df)

查看数据框:

df.show()
+------+------+------+
|userId|itemId|rating|
+------+------+------+
|     1|   101|   5.7|
|     2|   102|   8.8|
|     3|   103|   7.9|
|     4|   104|   9.1|
|     5|   105|   6.6|
|     6|   106|   8.3|
+------+------+------+

从数据框创建CoordinateMatrix:

from pyspark.mllib.linalg.distributed import CoordinateMatrix, MatrixEntry
coorRDD = df.rdd.map(lambda x: MatrixEntry(x[0], x[1], x[2]))
coorMatrix = CoordinateMatrix(coorRDD)

现在查看结果的数据类型:

type(coorMatrix)
pyspark.mllib.linalg.distributed.CoordinateMatrix