正确地从PySpark中的文件中读取类型

时间:2016-03-10 15:31:44

标签: python apache-spark dataframe pyspark

我有一个以制表符分隔的文件,其中包含

id1 name1   ['a', 'b']  3.0 2.0 0.0 1.0

即id,名称,包含一些字符串的列表以及一系列4个float属性。 我正在读这个文件

rdd = sc.textFile('myfile.tsv') \
    .map(lambda row: row.split('\t'))
df = sqlc.createDataFrame(rdd, schema)

我将模式设为

schema = StructType([
    StructField('id', StringType(), True),
    StructField('name', StringType(), True),
    StructField('list', ArrayType(StringType()), True),
    StructField('att1', FloatType(), True),
    StructField('att2', FloatType(), True),
    StructField('att3', FloatType(), True),
    StructField('att4', FloatType(), True)
])

问题是,从DataFrame上的collect判断,列表和属性都无法正确读取。事实上,我得到None所有人:

Row(id=u'id1', brand_name=u'name1', list=None, att1=None, att2=None, att3=None, att4=None)

我做错了什么?

1 个答案:

答案 0 :(得分:3)

它被正确阅读,它没有像你期望的那样工作。 Schema参数声明类型,以避免昂贵的模式推断,而不是如何转换数据。提供与声明的模式匹配的输入是您的责任。

这也可以通过数据源处理(查看inferSchemadf = rdd.toDF([f.name for f in schema.fields]) exprs = [ # You should excluding casting # on other complex types as well col(f.name).cast(f.dataType) if f.dataType.typeName() != "array" else col(f.name) for f in schema.fields ] df.select(*exprs) 选项)。它不会像数组一样处理复杂的类型。

由于您的架构基本上是平的,并且您知道类型,您可以尝试这样的事情:

{{1}}

使用字符串处理函数或UDF分别处理复杂类型。或者,既然你用Python读取数据,只需在创建DF之前强制执行所需的类型。