2016-07-14 23 views
10

Bối cảnh: Tôi có một DataFrame với 2 cột: từ và vectơ. Trường hợp loại cột của "vectơ" là VectorUDT.Cách chia Vector thành các cột - sử dụng PySpark

Một thí dụ:

word | vector 

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

Và tôi muốn có được điều này:

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

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

Câu hỏi:

Làm thế nào tôi có thể chia một cột với vectơ trong một số cột cho mỗi chiều sử dụng pyspark?

Cảm ơn trước

Trả lời

16

Một cách tiếp cận có thể là chuyển đổi sang và từ 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| 
## +-------+---+---+---+ 

Một giải pháp thay thế sẽ được tạo ra một 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

Hiệu suất khôn ngoan, đó là thông minh hơn nhiều để sử dụng các hàm '.map/.toDF' vì chúng hầu như luôn luôn nhanh hơn so với thực thi UDF. [Trừ khi bạn đang sử dụng định nghĩa 'vectorized udf' từ tia lửa 2.2+] – tmarthal

Các vấn đề liên quan