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

Posted

技术标签:

【中文标题】Scala/Spark - 如何获取所有子数组的第一个元素【英文标题】:Scala/Spark - How to get first elements of all sub-arrays 【发布时间】:2019-12-08 19:01:58 【问题描述】:

我在 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]]

我想获得一个只有每个子数组的第一个 Ints 的 Dataframe,例如:

[1003014, 15, 754, 1029530, 3066, 1066440, ...]

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

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

【问题讨论】:

嗨@twister9458,你能更清楚你的结构吗?另外,您使用的是哪个 API?数据框、数据集还是 RDD? 你好baitmbarek,谢谢你的回复,我在这种情况下使用DataFrames。我已经更正了我的问题 你能加个printSchema吗? 【参考方案1】:

对于 Spark >= 2.4,您可以使用 Higher-Order Function 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]|
+-----------------------------------+

火花

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

df.withColumn("exploded_array", explode(col("arrays")))
  .agg(collect_list(col("exploded_array")(0)))
  .show(false)

编辑:

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

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

【讨论】:

【参考方案2】:

使用 Spark 2.4:

val df = Seq(
  Seq(Seq(1.0,2.0),Seq(3.0,4.0))
).toDF("arrs")

df.show()

+--------------------+
|                arrs|
+--------------------+
|[[1.0, 2.0], [3.0...|
+--------------------+

df
 .select(expr("transform(arrs, x -> x[0])").as("arr_first"))
 .show()

+----------+
| arr_first|
+----------+
|[1.0, 3.0]|
+----------+

【讨论】:

谢谢你罗斯。 => topRecommendations.printSchema() 给出:root |-- user_id: integer (nullable = false) |-- recommendations: array (nullable = true) | |-- element: struct (containsNull = true) | | |-- canonical_id: integer (nullable = true) | | |-- rating: float (nullable = true) 表示 => 两列 [user_id: Int, Recommendations: element],建议是带有 [Int, float] 的元素结构类型

以上是关于Scala/Spark - 如何获取所有子数组的第一个元素的主要内容,如果未能解决你的问题,请参考以下文章

Scala Spark - 调用 createDataFrame 时获取重载方法

scala - Spark:如何在 groupedData 中获取带有条件的结果集

检索子文档中数组的第一项而不获取其他子文档

使用 Scala/Spark 列出目录中的文件(包括文件信息)

如何在窗口 scala/spark 中使用 partitionBy 函数

当结构中的所有值都为空时,如何在 Scala spark 中使结构为空?