Spark DataFrame如何区分不同的VectorUDT对象?

max*_*max 6 dataframe apache-spark pyspark apache-spark-ml apache-spark-mllib

我正在尝试了解DataFrame列类型.当然,DataFrame不是物化对象,它只是Spark的一组指令,将来转换为代码.但我想象这个类型列表表示在执行操作时可能在JVM内部实现的对象类型.

import pyspark
import pyspark.sql.types as T
import pyspark.sql.functions as F
data = [0, 3, 0, 4]
d = {}
d['DenseVector'] = pyspark.ml.linalg.DenseVector(data)
d['old_DenseVector'] = pyspark.mllib.linalg.DenseVector(data)
d['SparseVector'] = pyspark.ml.linalg.SparseVector(4, dict(enumerate(data)))
d['old_SparseVector'] = pyspark.mllib.linalg.SparseVector(4, dict(enumerate(data)))
df = spark.createDataFrame([d])
df.printSchema()
Run Code Online (Sandbox Code Playgroud)

四个向量值的列在printSchema()(或schema)中看起来相同:

root
 |-- DenseVector: vector (nullable = true)
 |-- SparseVector: vector (nullable = true)
 |-- old_DenseVector: vector (nullable = true)
 |-- old_SparseVector: vector (nullable = true)
Run Code Online (Sandbox Code Playgroud)

但是当我逐行检索它们时,它们会变得不同:

> for x in df.first().asDict().items():
  print(x[0], type(x[1]))
(2) Spark Jobs
old_SparseVector <class 'pyspark.mllib.linalg.SparseVector'>
SparseVector <class 'pyspark.ml.linalg.SparseVector'>
old_DenseVector <class 'pyspark.mllib.linalg.DenseVector'>
DenseVector <class 'pyspark.ml.linalg.DenseVector'>
Run Code Online (Sandbox Code Playgroud)

我对vector类型的含义感到困惑(相当于VectorUDT编写UDF的目的).如何DataFrame知道每vector列中哪四种矢量类型?这些向量列中的数据是存储在JVM中还是存储在python VM中?如果它不是这里列出的官方类型之一,那怎么来VectorUDT存储呢?DataFrame

(我知道四种矢量类型中的两种,mllib.linalg最终会被弃用.)

zer*_*323 8

为什么VectorUDT可以存储在DataFrame中

UDT又名用户定义类型应该是一个提示.Spark提供(现在是私有的)机制来存储自定义对象DataFrame.您可以在Spark SQL中查看如何为自定义类型定义架构的答案或者火花源的详细信息,但长话短说,它是关于解构对象并将它们编码为Catalyst类型.

我对矢量类型的含义感到困惑

很可能是因为你看错了.简短描述很有用,但它不能确定类型.相反,您应该检查架构.让我们创建另一个数据框:

import pyspark.mllib.linalg as mllib
import pyspark.ml.linalg as ml

df = sc.parallelize([
    (mllib.DenseVector([1, ]), ml.DenseVector([1, ])),
    (mllib.SparseVector(1, [0, ], [1, ]), ml.SparseVector(1, [0, ], [1, ]))
]).toDF(["mllib_v", "ml_v"])

df.show()

## +-------------+-------------+
## |      mllib_v|         ml_v|
## +-------------+-------------+
## |        [1.0]|        [1.0]|
## |(1,[0],[1.0])|(1,[0],[1.0])|
## +-------------+-------------+
Run Code Online (Sandbox Code Playgroud)

并检查数据类型:

{s.name: type(s.dataType) for s in df.schema}

## {'ml_v': pyspark.ml.linalg.VectorUDT,
##  'mllib_v': pyspark.mllib.linalg.VectorUDT}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,UDT类型是完全合格的,因此这里没有混淆.

DataFrame如何知道它在每个向量列中的四种向量类型中的哪一种?

如上所示,DataFrame只知道它的模式,可以区分ml/ mllib类型,但不关心矢量变量(稀疏或密集).

矢量类型由其type字段(byte字段,0 - >稀疏,1 - >密集)确定,但整体模式是相同的.在ml和之间的内部表示也没有区别mllib.

这些向量列中的数据是存储在JVM还是Python中

DataFrame是一个纯JVM实体.通过耦合的UDT类实现Python互操作性:

  • Scala UDT可以定义pyUDT属性.
  • Python UDT可以定义scalaUDT属性.