我想循环一个Spark数据集,并根据每一行的特征将特定值保存在Map中。我是Spark和Scala的新手,所以我加入了一个简单的示例,尝试在python中进行操作。
python中的最小工作示例:
SomeClass
其中数据是(大)spark数据集,类型为org.apache.spark.sql.Dataset [org.apache.spark.sql.Row]。
您知道使用Spark或Scala的方式吗?
答案 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)