我是Apache Spark
的新手。
以下是我在读取csv文件时创建的Spark dataframe
。
Parent Keyword Volume
P1 K1 100
P1 K2 200
P1 K3 150
P2 K4 100
P2 K5 200
我需要将上面的数据框转换为下面的数据框。该逻辑适用于属于同一父级的所有关键字都是相关的,并应按卷的排序顺序列出。例如,K1, K2, K3
属于同一父P1
,因此它们都是相关的。因此,对于K1
,相关的关键字是K2
和K3
。首先显示K2
,因为它的音量(200
)大于K3(150)
。
Keyword Related_keywords
K1 K2, K3
K2 K3, K1
K3 K2, K1
K4 K5
K5 K4
有人可以帮助我吗?我是Spark的新手,正在研究这个问题,可以使用groupBy
,但不知道如何将第一个数据帧转换为第二个数据帧。
答案 0 :(得分:1)
虽然可以使用groupBy
完成此操作,但是当您需要结果数据帧中的所有原始行时,窗口函数通常会更容易。我们可以使用collect_list
,但作为doc says,顺序是不确定的,因此让我们创建卷和关键字的元组:
val txt =
"""Parent Keyword Volume
|P1 K1 100
|P1 K2 200
|P1 K3 150
|P2 K4 100
|P2 K5 200""".stripMargin.lines
.map(_.split("\\s+").mkString("|"))
.toSeq
.toDS()
val df = spark.read
.option("inferSchema", true)
.option("header", true)
.option("delimiter", "|")
.csv(txt)
val win = Window.partitionBy($"Parent")
val df1 =
df.select($"Keyword",
collect_list(struct(-$"Volume", $"Keyword")).over(win) as "rel")
现在我们几乎有了所需的格式
df1.select(array_sort($"rel") as "Related_keywords")
.show(20, false)
输出:
+------------------------------------+
|Related_keywords |
+------------------------------------+
|[[-200, K5], [-100, K4]] |
|[[-200, K5], [-100, K4]] |
|[[-200, K2], [-150, K3], [-100, K1]]|
|[[-200, K2], [-150, K3], [-100, K1]]|
|[[-200, K2], [-150, K3], [-100, K1]]|
+------------------------------------+
但是,有两个问题,原始Keyword
将在列表中重复出现,并且所有关键字的前面都有负数。为了使自己更漂亮,我相信需要UDF:s(找不到用于解压缩元组的SQL函数):
val myudf = udf(
(keyword: String, rel: Seq[Row]) =>
rel
.collect {
case Row(volume: Int, kw: String) if kw != keyword => (volume, kw)
}
.sortBy(_._1)
.map(_._2))
df1.select($"Keyword", myudf($"Keyword", $"rel") as "Related_keywords")
.show(20, false)
输出:
+-------+----------------+
|Keyword|Related_keywords|
+-------+----------------+
|K4 |[K5] |
|K5 |[K4] |
|K1 |[K2, K3] |
|K2 |[K3, K1] |
|K3 |[K2, K1] |
+-------+----------------+