Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何将向量拆分为列-使用PySpark_Python_Apache Spark_Pyspark_Apache Spark Sql_Apache Spark Ml - Fatal编程技术网

Python 如何将向量拆分为列-使用PySpark

Python 如何将向量拆分为列-使用PySpark,python,apache-spark,pyspark,apache-spark-sql,apache-spark-ml,Python,Apache Spark,Pyspark,Apache Spark Sql,Apache Spark Ml,上下文:我有一个DataFrame,有两列:word和vector。其中“vector”的列类型为VectorUDT 例如: word | vector assert | [435,323,324,212...] 我想得到这个: word | v1 | v2 | v3 | v4 | v5 | v6 ...... assert | 435 | 5435| 698| 356|.... 问题: 如何使用PySpark将一列向量拆分为每个维度的几列 提前感谢Spark>=3.0.0

上下文:我有一个
DataFrame
,有两列:word和vector。其中“vector”的列类型为
VectorUDT

例如:

word    |  vector
assert  | [435,323,324,212...]
我想得到这个:

word   |  v1 | v2  | v3 | v4 | v5 | v6 ......
assert | 435 | 5435| 698| 356|....
问题:

如何使用PySpark将一列向量拆分为每个维度的几列


提前感谢

Spark>=3.0.0

由于Spark 3.0.0,这可以在不使用UDF的情况下完成

from pyspark.ml.functions import vector_to_array

(df
    .withColumn("xs", vector_to_array("vector")))
    .select(["word"] + [col("xs")[i] for i in range(3)]))

## +-------+-----+-----+-----+
## |   word|xs[0]|xs[1]|xs[2]|
## +-------+-----+-----+-----+
## | assert|  1.0|  2.0|  3.0|
## |require|  0.0|  2.0|  0.0|
## +-------+-----+-----+-----+
火花<3.0.0

一种可能的方法是在RDD之间进行转换:

from pyspark.ml.linalg import Vectors

df = sc.parallelize([
    ("assert", Vectors.dense([1, 2, 3])),
    ("require", Vectors.sparse(3, {1: 2}))
]).toDF(["word", "vector"])

def extract(row):
    return (row.word, ) + tuple(row.vector.toArray().tolist())

df.rdd.map(extract).toDF(["word"])  # Vector values will be named _2, _3, ...

## +-------+---+---+---+
## |   word| _2| _3| _4|
## +-------+---+---+---+
## | assert|1.0|2.0|3.0|
## |require|0.0|2.0|0.0|
## +-------+---+---+---+
另一种解决方案是创建UDF:

from pyspark.sql.functions import udf, col
from pyspark.sql.types import ArrayType, DoubleType

def to_array(col):
    def to_array_(v):
        return v.toArray().tolist()
    # Important: asNondeterministic requires Spark 2.3 or later
    # It can be safely removed i.e.
    # return udf(to_array_, ArrayType(DoubleType()))(col)
    # but at the cost of decreased performance
    return udf(to_array_, ArrayType(DoubleType())).asNondeterministic()(col)

(df
    .withColumn("xs", to_array(col("vector")))
    .select(["word"] + [col("xs")[i] for i in range(3)]))

## +-------+-----+-----+-----+
## |   word|xs[0]|xs[1]|xs[2]|
## +-------+-----+-----+-----+
## | assert|  1.0|  2.0|  3.0|
## |require|  0.0|  2.0|  0.0|
## +-------+-----+-----+-----+
有关Scala等效项,请参见


该函数将特征向量列转换为单独的列

上面zero323在解决方案中给出的提取函数使用toList,它创建一个Python列表对象,用Python浮点对象填充它,通过遍历列表找到所需的元素,然后需要将列表转换回JavaDouble;每行重复一次。使用rdd比to_数组udf慢得多,后者也调用toList,但两者都比让SparkSQL处理大部分工作的udf慢得多

将rdd extract和此处提出的阵列udf与以下udf进行比较的计时代码:

结果:

i_th         0.05964796099999958
flatten      0.4842299350000001
to_array     0.42978780299999997
extract      2.9254476840000017

对于试图将PySpark ML模型训练后生成的
rawPrediction
probability
列拆分为Pandas列的任何人,可以按如下方式拆分:

your_pandas_df['probability'].apply(lambda x: pd.Series(x.toArray()))
your_pandas_df['probability'].apply(lambda x: pd.Series(x.toArray()))

要将PySpark ML模型训练后生成的
rawPrediction
probability
列拆分为Pandas列,可以按如下方式拆分:

your_pandas_df['probability'].apply(lambda x: pd.Series(x.toArray()))
your_pandas_df['probability'].apply(lambda x: pd.Series(x.toArray()))

就性能而言,使用
.map/.toDF
函数要聪明得多,因为它们几乎总是比UDF实现更快。[除非您使用的是spark 2.2+中的
矢量化udf
定义]谢谢您的评论。RDDAPI不会在某个时候被弃用吗?因此,我认为后者是推荐的,或者我正在编写?请注意,从spark 2.3开始,
矢量化UDF
要求输入和输出coolumns都是java原语,因此,它不适用于此应用程序。相关JIRA票证对此进行了改进:@zero323-对我来说,UDF方式似乎已经奏效。如何将结果保存为DF?当我在最后做一个.show时,它会按照我想要的方式显示DF。似乎找不到命名/保存它的方法。请参阅,以获取性能更好的解决方案。(我在这两个方面都做了计时。如果我有声誉的话,我会将这一个标记为重复。)@hwrd你能分享一下你使用的基准测试代码吗?TIA.@user10465355作为“解决方案”添加到下面,因为它太大,无法发表评论。(这个组织有点古怪,因为我从Jupyter笔记本中取出了它,然后替换了%%timeit cell magic。)这是一些看起来很棒的代码,但它能做什么呢?你能解释一下使用的不同方法吗?@代码乘以此处接受的解决方案中Spark<3.0.0的两个函数和中提出的
ith
函数,以表明后一种解决方案更优越。你是在比较DAG构造,而不是实际的转换。我得到了以下错误:TypeError:“Column”对象不可调用