当数组很大时,在Scala中的Spark Dataframe中从数组列创建单独的列[重复]

Posted

技术标签:

【中文标题】当数组很大时,在Scala中的Spark Dataframe中从数组列创建单独的列[重复]【英文标题】:Create separate columns from array column in Spark Dataframe in Scala when array is large [duplicate] 【发布时间】:2018-09-11 12:44:26 【问题描述】:

我有两列:一列是整数类型,另一列是 linalg.Vector。我可以将 linalg.Vector 转换为数组。每个数组有 32 个元素。我想将数组中的每个元素转换为一列。所以输入是这样的:

column1                  column2
(3, 5, 25, ...., 12)           3
(2, 7, 15, ...., 10)           4
(1, 10, 12, ..., 35)           2

输出应该是:

column1_1  column1_2 column1_3 ......... column1_32     column 2
        3          5        25 .........         12            3
        2          7        15 .........         10            4
        1        1 0        12 .........         12            2

除了,在我的例子中,数组中有 32 个元素。使用有问题的方法太多了Convert Array of String column to multiple columns in spark scala

我尝试了几种方法,但都没有奏效。这样做的正确方法是什么?

非常感谢。

【问题讨论】:

***.com/questions/38110038/… 回答问题。我以前找不到它。谢谢 【参考方案1】:
scala> import org.apache.spark.sql.Column
scala> val df = Seq((Array(3,5,25), 3),(Array(2,7,15),4),(Array(1,10,12),2)).toDF("column1", "column2")
df: org.apache.spark.sql.DataFrame = [column1: array<int>, column2: int]

scala> def getColAtIndex(id:Int): Column = col(s"column1")(id).as(s"column1_$id+1")
getColAtIndex: (id: Int)org.apache.spark.sql.Column

scala> val columns: IndexedSeq[Column] = (0 to 2).map(getColAtIndex) :+ col("column2") //Here, instead of 2, you can give the value of n
columns: IndexedSeq[org.apache.spark.sql.Column] = Vector(column1[0] AS `column1_1`, column1[1] AS `column1_2`, column1[2] AS `column1_3`, column2)

scala> df.select(columns: _*).show
+---------+---------+---------+-------+
|column1_1|column1_2|column1_3|column2|
+---------+---------+---------+-------+
|        3|        5|       25|      3|
|        2|        7|       15|      4|
|        1|       10|       12|      2|
+---------+---------+---------+-------+

【讨论】:

您可能想要添加关于如何根据范围生成表达式的说明。 嗨,数组包含 32 个元素,而不是 3 个。我已编辑以使问题更清晰。很抱歉造成混淆。此外,这是 @user6910411 标记的 ***.com/questions/38110038/… 的副本 @Sujit,您的解决方案运行良好。但是,我无法从您的解决方案中弄清楚 column1 在创建 columns seq 时没有任何关于数据帧(df)的参考是如何工作的。 getColAtIndex 如何仅从 df 获取 column1 @Praveen-l,Spark 允许我们使用 Column 独立于数据框。如果它以这种方式使用,那么认为它只是在列的类型和名称上具有元数据。而且,spark 会根据其使用的上下文将其懒惰地应用于数据帧。 @Sujit,感谢您的澄清。【参考方案2】:

这可以通过编写类似的 UserDefinedFunction 来完成:

val getElementFromVectorUDF = udf(getElementFromVector(_: Vector, _: Int))
def getElementFromVector(vec: Vector, idx: Int) = 
   vec(idx)

你可以这样使用它:

df.select(
    getElementFromVectorUDF($"column1", 0) as "column1_0",
    ...
    getElementFromVectorUDF($"column1", n) as "column1_n",
)

我希望这会有所帮助。

【讨论】:

以上是关于当数组很大时,在Scala中的Spark Dataframe中从数组列创建单独的列[重复]的主要内容,如果未能解决你的问题,请参考以下文章

Spark/scala 中的 SQL 查询

如何在 Spark Scala 中将 WrappedArray 转换为 List?

如何使用 Scala 从 Spark 中的列表或数组创建行

Spark/Scala:对带有数组类型列的 DataFrame 中的某些组件的操作

Spark 2 将 scala 数组转换为 WrappedArray

Spark - Scala:当 json 数据分布在多行时,读取 json 文件作为数据帧不起作用?