Scala/Spark - 如何获取所有子数组的第一个元素

twi*_*458 2 scala apache-spark apache-spark-sql

我在 Spark 中有以下 DataFrame(我使用的是 Scala):

[[1003014, 0.95266926], [15, 0.9484202], [754, 0.94236785], [1029530, 0.880922], [3066, 0.7085166], [1066440, 0.69400793], [1045811, 0.663178], [1020059, 0.6274495], [1233982, 0.6112905], [1007801, 0.60937023], [1239278, 0.60044676], [1000088, 0.5789191], [1056268, 0.5747936], [1307569, 0.5676605], [10334513, 0.56592846], [930, 0.5446228], [1170206, 0.52525467], [300, 0.52473146], [2105178, 0.4972785], [1088572, 0.4815367]]
Run Code Online (Sandbox Code Playgroud)

我想获得一个只有每个子数组的第一个 Int 的 Dataframe,如下所示:

[1003014, 15, 754, 1029530, 3066, 1066440, ...]
Run Code Online (Sandbox Code Playgroud)

因此仅保留x[0]上面列出的数组的每个子数组 x 。

我是 Scala 新手,找不到合适的匿名映射函数。预先感谢您的任何帮助

bla*_*hop 5

对于Spark >= 2.4,您可以使用高阶函数 transform和 lambda 函数来提取每个值数组的第一个元素。

scala> df.show(false)

+----------------------------------------------------------------------------------------+
|arrays                                                                                  |
+----------------------------------------------------------------------------------------+
|[[1003014.0, 0.95266926], [15.0, 0.9484202], [754.0, 0.94236785], [1029530.0, 0.880922]]|
+----------------------------------------------------------------------------------------+

scala> df.select(expr("transform(arrays, x -> x[0])").alias("first_array_elements")).show(false)

+-----------------------------------+
|first_array_elements               |
+-----------------------------------+
|[1003014.0, 15.0, 754.0, 1029530.0]|
+-----------------------------------+
Run Code Online (Sandbox Code Playgroud)

火花<2.4

分解初始数组,然后聚合collect_list以收集每个子数组的第一个元素:

df.withColumn("exploded_array", explode(col("arrays")))
  .agg(collect_list(col("exploded_array")(0)))
  .show(false)
Run Code Online (Sandbox Code Playgroud)

编辑:

如果数组包含结构体而不是子数组,只需更改使用点作为结构体元素的访问方法:

val transfrom_expr = "transform(arrays, x -> x.canonical_id)"
df.select(expr(transfrom_expr).alias("first_array_elements")).show(false)
Run Code Online (Sandbox Code Playgroud)