簡體   English   中英

如何聚合Spark數據框以使用Scala獲取稀疏向量?

[英]How to aggregate a Spark data frame to get a sparse vector using Scala?

我在Spark中有一個類似下面的數據框,我想用id列對它進行分組,然后對於分組數據中的每一行,我需要創建一個稀疏向量,其中包含索引指定的index處的weight列中的元素柱。 稀疏矢量的長度是已知的,例如1000。

數據幀df

+-----+------+-----+
|   id|weight|index|
+-----+------+-----+
|11830|     1|    8|
|11113|     1|    3|
| 1081|     1|    3|
| 2654|     1|    3|
|10633|     1|    3|
|11830|     1|   28|
|11351|     1|   12|
| 2737|     1|   26|
|11113|     3|    2|
| 6590|     1|    2|
+-----+------+-----+

我讀過這個類似於我想做的事情,但是對於一個rdd。 有沒有人知道使用Scala在Spark中為數據框執行此操作的好方法?

到目前為止,我的嘗試是首先收集權重和索引,如下所示:

val dfWithLists = df
    .groupBy("id")
    .agg(collect_list("weight") as "weights", collect_list("index") as "indices"))

看起來像:

+-----+---------+----------+
|   id|  weights|   indices|
+-----+---------+----------+
|11830|   [1, 1]|   [8, 28]|
|11113|   [1, 3]|    [3, 2]|
| 1081|      [1]|       [3]|
| 2654|      [1]|       [3]|
|10633|      [1]|       [3]|
|11351|      [1]|      [12]|
| 2737|      [1]|      [26]|
| 6590|      [1]|       [2]|
+-----+---------+----------+

然后我定義一個udf並做這樣的事情:

import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.sql.functions.udf

def toSparseVector: ((Array[Int], Array[BigInt]) => Vector) = {(a1, a2) => Vectors.sparse(1000, a1, a2.map(x => x.toDouble))}
val udfToSparseVector = udf(toSparseVector)

val dfWithSparseVector = dfWithLists.withColumn("SparseVector", udfToSparseVector($"indices", $"weights"))

但這似乎不起作用,感覺應該有一個更簡單的方法來做到這一點,而不需要首先收集權重和索引列表。

我對Spark,Dataframes和Scala很新,所以任何幫助都非常受歡迎。

您必須收集它們,因為向量必須是本地的,單機: https//spark.apache.org/docs/latest/mllib-data-types.html#local-vector

對於創建稀疏向量,您有2個選項,使用無序(索引,值)對或指定索引和值數組: https//spark.apache.org/docs/latest/api/scala/index.html#org。 apache.spark.mllib.linalg.Vectors $

如果您可以將數據轉換為其他格式(透視),您還可以使用VectorAssembler: https ://spark.apache.org/docs/latest/ml-features.html#vectorassembler

通過一些小的調整,您可以使您的方法工作:

:paste
// Entering paste mode (ctrl-D to finish)

import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LabeledPoint

val df = Seq((11830,1,8), (11113, 1, 3), (1081, 1,3), (2654, 1, 3), (10633, 1, 3), (11830, 1, 28), (11351, 1, 12), (2737, 1, 26), (11113, 3, 2), (6590, 1, 2)).toDF("id", "weight", "index")

val dfWithFeat = df
  .rdd
  .map(r => (r.getInt(0), (r.getInt(2), r.getInt(1).toDouble)))
  .groupByKey()
  .map(r => LabeledPoint(r._1, Vectors.sparse(1000, r._2.toSeq)))
  .toDS

dfWithFeat.printSchema
dfWithFeat.show(10, false)


// Exiting paste mode, now interpreting.

root
|-- label: double (nullable = true)
|-- features: vector (nullable = true)

+-------+-----------------------+
|label  |features               |
+-------+-----------------------+
|11113.0|(1000,[2,3],[3.0,1.0]) |
|2737.0 |(1000,[26],[1.0])      |
|10633.0|(1000,[3],[1.0])       |
|1081.0 |(1000,[3],[1.0])       |
|6590.0 |(1000,[2],[1.0])       |
|11830.0|(1000,[8,28],[1.0,1.0])|
|2654.0 |(1000,[3],[1.0])       |
|11351.0|(1000,[12],[1.0])      |
+-------+-----------------------+

dfWithFeat: org.apache.spark.sql.Dataset[org.apache.spark.mllib.regression.LabeledPoint] = [label: double, features: vector]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM