从csv加载数据帧,丢弃所有不遵循模式的内容

时间:2019-05-03 20:35:36

标签: csv apache-spark apache-spark-sql

我正在尝试从csv文件读取并将其加载到数据帧中。现在,我尝试了以下方法。

    val schema = StructType(Seq(
      StructField("key", StringType, true),
      StructField("value", DoubleType, false)
    ))
    val df = sc.read.schema(schema)
      .option("mode", "DROPMALFORMED")
      .csv("C:\\Users\\raam\\IdeaProjects\\myPlayGround\\abc.csv")
    df.show()

我的csv看起来像这样

qqq
a,1
b,2.2
c,xyz
d,4.5
e,asfsdfsdf 
dd,
f,3.1
2,
,6.6

我的输出是

+----+-----+
| key|value|
+----+-----+
|   a|  1.0|
|   b|  2.2|
|   d|  4.5|
|  dd| null|
|   f|  3.1|
|   2| null|
|null|  6.6|
+----+-----+

在第二个StrcutField中,nullable为false,为什么我的df中的第四行和第六行呢? 另外,它们是一种在读取时创建两个单独的df的方法,以便可以将丢弃的行放在一个单独的文件中吗?

1 个答案:

答案 0 :(得分:1)

DROPMALFORMED模式会删除不符合模式的记录(在您的情况下为非数字值记录),但是它会忽略可为空性。看一下以下问题:SPARK-10848SPARK-25545this pull request,以了解其基本原理。如您所见,它不受欢迎,有些人试图对其进行修复,但到目前为止没有成功。

然后您需要显式地处理空记录。

val schema = StructType(Seq(
  StructField("key", StringType, true),
  StructField("value", DoubleType, false),
  StructField("corruptRecord", StringType, true)
))

val df = spark.read.schema(schema).
  option("mode", "PERMISSIVE").
  option("columnNameOfCorruptRecord", "corruptRecord").
  csv("abc.csv")

def isValid = 'corruptRecord.isNull && 'value.isNotNull
val validDf = df.filter(isValid)
val invalidDf = df.filter(!isValid)

isValid可以用更通用的方式定义:

def isValid = schema.filter(!_.nullable)
  .foldLeft('corruptRecord.isNull)((acc, f) => acc && col(f.name).isNotNull)

至少在没有嵌套结构/数组的情况下。