如何通过pyspark

时间:2019-04-22 08:23:28

标签: python hive pyspark scipy

我有一个rdd,它的每一行都包含三种数据类型。例如

from pyspark.sql import SparkSession
from scipy.sparse import csc_matrix
import numpy as np
from pyspark.sql.types import StructType,StructField,FloatType,IntegerType,ArrayType

# create sparse matrix
row = np.array([0, 2, 2, 0, 1, 2])
col = np.array([0, 0, 1, 2, 2, 2])
data = np.array([1, 2, 3, 4, 5, 6])
sp_mat = csc_matrix((data, (row, col)), shape=(3, 3))

# create rdd
sqlContext = SparkSession.builder.appName("test").enableHiveSupport().getOrCreate()
sp_data = [(0,12.1,sp_mat),(1,21.32,sp_mat),(2,21.2,sp_mat)]
spare_rdd = sqlContext.sparkContext.parallelize(sp_data)
print(spare_rdd.take(3)) 

# print
[(0, 12.1, <3x3 sparse matrix of type '<type 'numpy.int64'>' with 6 stored elements in Compressed Sparse Column format>)
,(1, 21.32, <3x3 sparse matrix of type '<type 'numpy.int64'>' with 6 stored elements in Compressed Sparse Column format>)
,(2, 21.2, <3x3 sparse matrix of type '<type 'numpy.int64'>' with 6 stored elements in Compressed Sparse Column format>)]

前两种数据类型是int和float。三种数据类型是稀疏稀疏矩阵。我想将此rdd数据写入配置单元表。但是我不知道保存稀疏矩阵的形式或字段。

所以我的问题如下:

  1. 如何为scipy稀疏矩阵创建蜂巢表?

    CREATE EXTERNAL TABLE spare_table(
      id int,
      value float,
      ...  <---- One or more field or struct for scipy sparse matrix 
    )
    stored as orc tblproperties ("orc.compress"="SNAPPY");
    
  2. 如何通过pyspark将scipy稀疏矩阵保存到上表中?如果我通过df = sqlContext.createDataFrame(spare_rdd, schema=['id', 'value', 'scipy'])将rdd转换为数据帧,则会显示错误:

      

    TypeError:不支持的类型:

不存储scipy类型的解决方案也是可以接受的。唯一的要求是该解决方案可以支持再次进行稀疏矩阵写入和读取。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我终于找到了解决方案。我可以将稀疏稀疏矩阵的indicesindptrdatashape存储到配置单元表中以实现此目的。当我再次从蜂巢表中读取数据时,我可以基于它们重新创建一个稀疏矩阵。 首先,我应该创建一个配置单元表,如下所示:

CREATE EXTERNAL TABLE spare_table(
  id int,
  value float,
  indices array<int>,
  indptr array<int>,
  data array<int>,
  shape array<int>
)
stored as orc tblproperties ("orc.compress"="SNAPPY");

然后,我通过将稀疏稀疏矩阵分解为indicesindptrdatashape将rdd转换为数据帧。

grid_img_df = spare_rdd.map(lambda x: [
    x[0]
    ,x[1]
    ,x[2].indices.tolist()
    ,x[2].indptr.tolist()
    ,x[2].data.tolist()
    ,[int(shape) for shape in x[2].shape]])

df = sqlContext.createDataFrame(grid_img_df, schema=['id','value','indices','indptr','data','shape'])
df.show()
+---+-----+------------------+------------+------------------+------+
| id|value|           indices|      indptr|              data| shape|
+---+-----+------------------+------------+------------------+------+
|  0| 12.1|[0, 2, 2, 0, 1, 2]|[0, 2, 3, 6]|[1, 2, 3, 4, 5, 6]|[3, 3]|
|  1|21.32|[0, 2, 2, 0, 1, 2]|[0, 2, 3, 6]|[1, 2, 3, 4, 5, 6]|[3, 3]|
|  2| 21.2|[0, 2, 2, 0, 1, 2]|[0, 2, 3, 6]|[1, 2, 3, 4, 5, 6]|[3, 3]|
+---+-----+------------------+------------+------------------+------+

最后,我把它写在蜂巢中。

df.registerTempTable("df_table")
sqlContext.sql(""" INSERT overwrite TABLE spare_table 
                    select id
                            ,value
                            ,indices
                            ,indptr
                            ,data
                            ,shape
                            from df_table""")

从配置单元表读取数据并将其转换为稀疏稀疏矩阵的代码如下:

rdd = df.rdd.map(lambda row:(row.id,row.value,csc_matrix((row.data,row.indices,row.indptr),shape=row.shape)))