从数据集的行中选择一列

时间:2019-10-22 10:33:58

标签: scala apache-spark apache-spark-sql

我想循环一个Spark数据集,并根据每一行的特征将特定值保存在Map中。我是Spark和Scala的新手,所以我加入了一个简单的示例,尝试在python中进行操作。

python中的最小工作示例:

SomeClass

其中数据是(大)spark数据集,类型为org.apache.spark.sql.Dataset [org.apache.spark.sql.Row]。

您知道使用Spark或Scala的方式吗?

3 个答案:

答案 0 :(得分:1)

您无法循环Dataset的内容,因为在运行此代码的计算机上无法访问它们,而是分散在(可能有许多)不同的工作程序节点上。这是像spark这样的分布式执行引擎的基本概念。

相反,您必须以一种功能(将映射,过滤,归约,...操作分散到工作程序)或声明性(对工作程序执行的sql查询)的方式操纵数据。

要实现您的目标,您可以对数据进行映射,以检查名称是否等于“ Yan”,然后从那里继续。转换之后,您可以collect将数据框转换为字典。

您还应该检查使用Spark和地图的方法:似乎您想在mydict中为data的每个元素创建一个条目。这意味着您的数据足够小,以至于您实际上不必使用Spark,或者由于它不适合驱动程序内存而可能会失败。

答案 1 :(得分:1)

我认为您正在寻找类似的东西。如果最终的df不大,则可以将其收集并存储为地图。

scala> df.show()
+---+----+--------+
| id|name|surrname|
+---+----+--------+
|  1| Yan|  abc123|
|  2| Abc|  def123|
+---+----+--------+


scala> df.select('id, when('name === "Yan", 'surrname).otherwise("Random lad")).toDF("K","V").show()
+---+----------+
|  K|         V|
+---+----------+
|  1|    abc123|
|  2|Random lad|
+---+----------+

答案 2 :(得分:1)

这是一种简单的方法,但是请注意collect(),因为它会收集驱动程序中的数据。数据应该能够适合驱动程序。

我不建议您这样做。

var df: DataFrame = Seq(
  ("1", "Yan", "surname1"),
  ("2", "Yan1", "surname2"),
  ("3", "Yan", "surname3"),
  ("4", "Yan2", "surname4")
).toDF("id", "name", "surname")

val myDict = df.withColumn("newName", when($"name" === "Yan", $"surname").otherwise("RandomeName"))
  .rdd.map(row => (row.getAs[String]("id"), row.getAs[String]("newName")))
  .collectAsMap()

myDict.foreach(println)

输出:

(2,RandomeName)
(1,surname1)
(4,RandomeName)
(3,surname3)