scala - 如何从数据框在 scala 中创建地图字段?
问题描述
我有两个数据框如下:
df1:
language (column name)
tamil
telugu
hindi
df2:
id keywords
101 ["tamildiary", "tamilkeyboard", "telugumovie"]
102 ["tamilmovie"]
103 ["hindirhymes", "hindimovie"]
使用这两个数据框,我需要创建如下所示的内容。(基本上,需要找到针对每个 id 的语言特定关键字的数量并将它们存储在地图中)
id keywords
101 {"tamil":2, "telugu":1}
102 {"tamil":1}
103 {"hindi":2}
谁能帮我做这件事。非常感谢!
解决方案
regexp_replace
考虑使用正则表达式匹配具有前导语言关键字的字符串的两个 DataFrame ,然后是几个groupBy
s 来聚合一个数组(language, count)
,然后通过 转换为映射map_from_entries
:
val df1 = Seq("tamil", "telugu", "hindi").toDF("language")
val df2 = Seq(
(101, Seq("tamildiary", "tamilkeyboard", "telugumovie")),
(102, Seq("tamilmovie")),
(103, Seq("hindirhymes", "hindimovie"))
).toDF("id", "keywords")
val pattern = concat(lit("^"), df1("language"), lit(".*"))
df2.
withColumn("keyword", explode($"keywords")).as("df2").
join(df1.as("df1"), regexp_replace($"df2.keyword", pattern, lit("")) =!= $"df2.keyword").
groupBy("id", "language").agg(size(collect_list($"language")).as("count")).
groupBy("id").agg(map_from_entries(collect_list(struct($"language", $"count"))).as("keywords")).
show(false)
// +---+-------------------------+
// |id |keywords |
// +---+-------------------------+
// |101|[tamil -> 2, telugu -> 1]|
// |103|[hindi -> 2] |
// |102|[tamil -> 1] |
// +---+-------------------------+
对于Spark 2.0 - 2.3
,创建一个 UDF 来模仿map_from_entries
仅在 中可用的功能Spark 2.4+
:
import org.apache.spark.sql.Row
val arrayToMap = udf{ (arr: Seq[Row]) =>
arr.map{ case Row(k: String, v: Int) => (k, v) }.toMap
}
df2.
withColumn("keyword", explode($"keywords")).as("df2").
join(df1.as("df1"), regexp_replace($"df2.keyword", pattern, lit("")) =!= $"df2.keyword").
groupBy("id", "language").agg(size(collect_list($"language")).as("count")).
groupBy("id").agg(arrayToMap(collect_list(struct($"language", $"count"))).as("keywords")).
show(false)
作为旁注,以下是通过 SQL 表达式的正则表达式匹配条件的几个替代方案:
使用regexp_extract
:
expr("regexp_extract(df2.keyword, concat('^(', df1.language, ').*'), 1) = df1.language")
使用rlike
:
expr("df2.keyword rlike concat('^', df1.language, '.*')")
推荐阅读
- csv - 我如何在 quicksight 中刷新 csv 数据集而不是替换数据集,因为这会丢失我的计算
- excel - 我需要一个输入框条目来做两件事
- google-apps-script - Spreadsheet.flush 在我的 Google Apps 脚本上无法正常工作
- python - Python中的字体图形
- python - 在循环中创建多维 python 列表
- .net - 使用 Visual Studio 2017 构建 Docker 失败,因为在使用私有 nuget 源的 dotnet 还原期间超时
- python - 如何在循环中分配多个变量
- javascript - 如何在javascript中将键值对添加到关联数组
- python - 链表中虚拟节点和指针的说明
- python - 如果我峰之间有多少空间与一个点是否是峰无关,那么将宽度设置为什么?[scipy.signal.find_peaks_cwt]