我正在尝试从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的方法,以便可以将丢弃的行放在一个单独的文件中吗?
答案 0 :(得分:1)
DROPMALFORMED模式会删除不符合模式的记录(在您的情况下为非数字值记录),但是它会忽略可为空性。看一下以下问题:SPARK-10848,SPARK-25545和this 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)
至少在没有嵌套结构/数组的情况下。