当数组很大时,在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 中将 WrappedArray 转换为 List?
Spark/Scala:对带有数组类型列的 DataFrame 中的某些组件的操作