我的数据集包含一个包含数组的字段,如下所示:
{ "name" : "James", "subjects" : [ "english", "french", "botany" ] },
{ "name" : "neo", "subjects" : [ "english", "physics" ] },
{ "name" : "john", "subjects" : [ "spanish", "mathematics" ] }
现在我想通过传递 Column 对象来使用 Dataset.filter 函数进行过滤。我尝试了列的 isin 函数和函数的 array_contains 函数,但是没有用。
有没有办法创建 Column 对象来过滤数组,其中数组字段包含其中一个值?
答案 0 :(得分:2)
有多种方法可以执行此操作 - 一旦您隐式导入Encoder
:
import sparkSession.implicits._
首先,您可以将DataFrame
DataSet[Row]
转换为强类型DataSet[Student]
,这样您就可以熟悉(至少如果您了解Scala)Scala成语:
case class Student(name: String, subjects: Seq[String])
sparkSession.read.json("my.json")
.as[Student]
.filter(_.subjects.contains("english"))
您还可以在Column
中使用纯{ - 1}}方法,并使用有用的Spark DataFrame
library中的array_contains
:
functions
最后,虽然它可能对您没有帮助,但请记住,您也可以使用同一sparkSession.read.json("my.json").filter(array_contains($"subjects", "english"))
库中的explode
为每个主题添加自己的行:
functions
答案 1 :(得分:1)
Spark SQL的DataFrameReader支持所谓的JSON Lines文本格式(又名换行符分隔的JSON ),其中:
每一行都是有效的JSON值
您可以使用json
运算符来读取数据集。
// on command line
$ cat subjects.jsonl
{ "name" : "James", "subjects" : [ "english", "french", "botany" ] }
{ "name" : "neo", "subjects" : [ "english", "physics" ] }
{ "name" : "john", "subjects" : [ "spanish", "mathematics" ] }
// in spark-shell
scala> val subjects = spark.read.json("subjects.jsonl")
subjects: org.apache.spark.sql.DataFrame = [name: string, subjects: array<string>]
scala> subjects.show(truncate = false)
+-----+-------------------------+
|name |subjects |
+-----+-------------------------+
|James|[english, french, botany]|
|neo |[english, physics] |
|john |[spanish, mathematics] |
+-----+-------------------------+
scala> subjects.printSchema
root
|-- name: string (nullable = true)
|-- subjects: array (nullable = true)
| |-- element: string (containsNull = true)
有了这个,当你找到处理基于array
的输入的收集功能时,你应该看一下函数library。 array_contains
或explode
。
你可以在@Vidya的答案中找到。
缺少的是我心爱的Dataset.flatMap,鉴于subjects
数据集,可以按如下方式使用:
scala> subjects
.as[(String, Seq[String])] // convert to Dataset[(String, Seq[String])] for more type-safety
.flatMap { case (student, subjects) => subjects.map(s => (student, s)) } // typed expand
.filter(_._2.toLowerCase == "english") // filter out non-english subjects
.show
+-----+-------+
| _1| _2|
+-----+-------+
|James|english|
| neo|english|
+-----+-------+
然而,这并不像它的for-comprehension版本那样好/好。
val subjectsDF = subjects.as[(String, Seq[String])]
val englishStudents = for {
(student, ss) <- subjectsDF // flatMap
subject <- ss // map
if subject.toLowerCase == "english"
} yield (student, subject)
scala> englishStudents.show
+-----+-------+
| _1| _2|
+-----+-------+
|James|english|
| neo|english|
+-----+-------+
此外,从Spark 2.2 (即将发布)开始,您可以使用DataFrameReader.json
运算符来阅读Dataset[String]
。
scala> spark.version
res0: String = 2.3.0-SNAPSHOT
import org.apache.spark.sql.Dataset
val subjects: Dataset[String] = Seq(
"""{ "name" : "James", "subjects" : [ "english", "french", "botany" ] }""",
"""{ "name" : "neo", "subjects" : [ "english", "physics" ] }""",
"""{ "name" : "john", "subjects" : [ "spanish", "mathematics" ]}""").toDS
scala> spark.read.option("inferSchema", true).json(subjects).show(truncate = false)
+-----+-------------------------+
|name |subjects |
+-----+-------------------------+
|James|[english, french, botany]|
|neo |[english, physics] |
|john |[spanish, mathematics] |
+-----+-------------------------+
答案 2 :(得分:0)
据我了解,您正在尝试根据包含特定字符串的数组列在DataFrame中查找记录。例如,在这种情况下,您尝试查找包含特定主题的记录,例如“英语”。
首先创建一个示例数据框
import org.apache.spark.sql.functions._
val json_data = """[{ "name" : "James", "subjects" : [ "english", "french", "botany" ] },
{ "name" : "neo", "subjects" : [ "english", "physics" ] },
{ "name" : "john", "subjects" : [ "spanish", "mathematics" ] }]"""
val df = spark.read.json(Seq(json_data).toDS).toDF
现在,让我们尝试查找包含主题“ english”的记录。在这里,我们可以使用spark 2.4.0中提供的高阶函数“ array_contains”。
df.filter(array_contains($"subjects", "english")).show(truncate=false)
//输出
+-----+-------------------------+------------+
|name |subjects |contains_eng|
+-----+-------------------------+------------+
|James|[english, french, botany]|true |
|neo |[english, physics] |true |
+-----+-------------------------+------------+
您可以在此处(scala和python)找到有关这些功能的更多详细信息。
我希望这会有所帮助。