Spark toDF()/ createDataFrame()类型推断无法按预期工作

时间:2017-11-13 08:10:26

标签: apache-spark pyspark schema spark-dataframe type-inference

df = sc.parallelize([('1','a'),('2','b'),('3','c')]).toDF(['should_be_int','should_be_str'])
df.printSchema()

产生

  


  | - should_be_int:string(nullable = true)
  | - should_be_str:string(nullable = true)

根据文档,注意should_be_int具有string数据类型: https://spark.apache.org/docs/latest/sql-programming-guide.html#inferring-the-schema-using-reflection

  

Spark SQL可以将Row对象的RDD转换为DataFrame,并进行推断   数据类型。通过传递键/值列表来构造行   成为Row类的kwargs。此列表的键定义了   表的列名,和类型是通过抽样来推断的   整个数据集,类似于在JSON上执行的推理   文件。

在读取分隔文件(如

)时,架构推断按预期工作
spark.read.format('csv').option('inferSchema', True)...

但不是在使用toDF()/ createDataFrame()API调用时。

Spark 2.2。

更新:更详细的解释,解释为什么上面的例子中的'1'用单引号(字符串而不是'int'类型的1)。

'1'的类型为'str'。这是专门为了证明我的观点。 正如我在jira描述中所说的那样,我希望在读取分隔文件时(在旧的spark-csv spark模块中)有相同的模式推断可以正常工作。

例如,我们使用sc.binaryRecords(hdfsFile, recordLength)读取固定宽度文件,然后在rdd.map()之后基本上获得一个包含所有元素/“列”字符串的非常宽的建模数据集。

我们希望使用相同的spark-csv类型的模式推断,因此Spark通过分析所有字符串来映射字符串,以提供实际的数据类型。

当我们希望toDF()和/或createDataFrame() API调用通过读取整个数据集来参与相同的模式推理时,我们还有其他方案,并参见上面的示例,“1”,“2” ,'3'“最不常见”类型是类型'int' - 再次,正是spark-csv逻辑的作用。这可能在Spark?

此外,您可以将此视为Pandas的infer_dtype()电话:

https://pandas.pydata.org/pandas-docs/stable/generated/pandas.api.types.infer_dtype.html?highlight=infer#pandas.api.types.infer_dtype

PS。我相信这是一个错误(至少行为与文档不匹配),也创建了Spark jira - https://issues.apache.org/jira/browse/SPARK-22505

PPS。这就是它如何与spark-csv模式推理一起使用:

$ cat 123.txt
should_be_int,should_be_str
1,a
2,b
3,c

spark-csv example

1 个答案:

答案 0 :(得分:2)

在Spark 2.3+中,可以使用以下方法解决此问题:

enter image description here

它已在Spark 2.2中提供,但仅适用于Scala API。

更多关于此阅读 - SPARK-15463SPARK-22112SPARK-22505