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()
电话:
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
答案 0 :(得分:2)
在Spark 2.3+中,可以使用以下方法解决此问题:
它已在Spark 2.2中提供,但仅适用于Scala API。
更多关于此阅读 - SPARK-15463, SPARK-22112, SPARK-22505