我有一个带有以下架构和类数据的spark数据帧:
>ab
ab: org.apache.spark.sql.DataFrame = [block_number: bigint, collect_list(to): array<string> ... 1 more field]
>ab.printSchema
root |-- block_number: long (nullable = true)
|-- collect_list(to): array (nullable = true)
| |-- element: string (containsNull = true)
|-- collect_list(from): array (nullable = true)
| |-- element: string (containsNull = true)
我想简单地合并这两列中的数组。我试图在网上找到一个简单的解决方案,但没有运气。基本上我的问题归结为两个问题。
首先,我知道解决方案可能涉及地图功能。我无法找到任何可以实际编译的语法,所以现在请接受我最好的尝试:
ab.rdd.map(
row => {
val block = row.getLong(0)
val array1 = row(1).getAs[Array<string>]
val array1 = row(1).getAs[Array<string>]
}
)
基本上问题1非常简单,并且自从我第一次开始在Scala中使用map之后一直重复出现的问题:我无法弄清楚如何从列中提取任意类型的任意字段。我知道对于原始类型,你有row.getLong(0)
之类的东西,但是我不明白如何对数组类型这样做。
我在某处看到像row.getAs[Array<string>](1)
这样的东西应该有用,但是当我尝试它时我得到了错误
error: identifier expected but ']' found.
val array1 = row.getAs[Array<string>](1)`
据我所知,这正是我在其他情况下看到的语法,但我不知道为什么它不起作用。我想我之前看到的其他语法看起来像row(1).getAs[Type]
,但我不确定。
第二个问题是:一旦我可以接触这两个数组,合并它们的最佳方法是什么?使用交叉函数?或者对整个过程有更好的方法吗?例如使用砖房包装?
任何帮助将不胜感激。
最佳,
保
答案 0 :(得分:0)
您不需要切换到RDD API,您可以使用Dataframe UDF这样做:
val mergeArrays = udf((arr1:Seq[String],arr2:Seq[String]) => arr1++arr2)
df
.withColumn("merged",mergeArrays($"collect_list(from)",$"collect_list(to)"))
.show()
上面的UDF只是对数组进行汇总(使用++
运算符),您还可以使用union
或intersect
等,具体取决于您想要实现的目标。
使用RDD API,解决方案如下所示:
df.rdd.map(
row => {
val block = row.getLong(0)
val array1 = row.getAs[Seq[String]](1)
val array2 = row.getAs[Seq[String]](2)
(block,array1++array2)
}
).toDF("block","merged") // back to Dataframes