我有一个以制表符分隔的文件,其中包含
行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)
我做错了什么?
答案 0 :(得分:3)
它被正确阅读,它没有像你期望的那样工作。 Schema参数声明是类型,以避免昂贵的模式推断,而不是如何转换数据。提供与声明的模式匹配的输入是您的责任。
这也可以通过数据源处理(查看inferSchema
和df = 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之前强制执行所需的类型。