2016-07-14 11 views
10

Kontext: Ich habe eine DataFrame mit 2 Spalten: Wort und Vektor. Wenn der Spaltentyp "Vektor" VectorUDT ist.So spalten Sie Vektor in Spalten - mit PySpark

Ein Beispiel:

word | vector 

assert | [435,323,324,212...] 

Und ich will diese bekommen:

word | v1 | v2 | v3 | v4 | v5 | v6 ...... 

assert | 435 | 5435| 698| 356|.... 

Frage:

Wie kann ich für jede Dimension eine Spalte mit Vektoren in mehrere Spalten aufgeteilt mit pyspark?

Vielen Dank im Voraus

Antwort

16

Ein möglicher Ansatz ist vom und zum RDD zu konvertieren:

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| 
## +-------+---+---+---+ 

Eine alternative Lösung wäre, erstellen Sie eine 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() 
    return udf(to_array_, ArrayType(DoubleType()))(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| 
## +-------+-----+-----+-----+ 
+0

Performance weise, es ist viel klüger, die '.map/.toDF'-Funktionen zu verwenden, da sie fast immer schneller als die UDF-Implementierung sind. [Es sei denn, du verwendest eine 'vektorisierte udf' Definition von funke 2.2+] – tmarthal

Verwandte Themen