使用架构从 pyspark 中的 json 文件读取固定宽度的文件



我有固定宽度的文件,如下所示

00120181120xyz12341
00220180203abc56792
00320181203pqr25483 

以及指定架构的相应JSON文件:

{"Column":"id","From":"1","To":"3"}
{"Column":"date","From":"4","To":"8"}
{"Column":"name","From":"12","To":"3"}
{"Column":"salary","From":"15","To":"5"}

我使用以下方法将架构文件读入数据帧:

SchemaFile = spark.read
.format("json")
.option("header","true")
.json('C:TempschemaFileschema.json')
SchemaFile.show()
#+------+----+---+
#|Column|From| To|
#+------+----+---+
#|    id|   1|  3|
#|  date|   4|  8|
#|  name|  12|  3|
#|salary|  15|  5|
#+------+----+---+

同样,我将固定宽度的文件解析为 pyspark 数据帧,如下所示:

File = spark.read
.format("csv")
.option("header","false")
.load("C:Tempsamplefile.txt")
File.show()
#+-------------------+
#|                _c0|
#+-------------------+
#|00120181120xyz12341|
#|00220180203abc56792|
#|00320181203pqr25483|
#+-------------------+

我显然可以对每列的位置和长度的值进行硬编码,以获得所需的输出:

from pyspark.sql.functions import substring
data = File.select(
substring(File._c0,1,3).alias('id'),
substring(File._c0,4,8).alias('date'),
substring(File._c0,12,3).alias('name'),
substring(File._c0,15,5).alias('salary')
)
data.show()
#+---+--------+----+------+
#| id|    date|name|salary|
#+---+--------+----+------+
#|001|20181120| xyz| 12341|
#|002|20180203| abc| 56792|
#|003|20181203| pqr| 25483|
#+---+--------+----+------+

但是,如何使用SchemaFile数据帧指定行的宽度和列名称,以便在运行时动态应用架构(无需硬编码)?

这里最简单的方法是collectSchemaFile的内容并遍历其行以提取所需的数据。

首先将架构文件作为 JSON 读入数据帧。然后调用 collect 并将每一行映射到字典:

sfDict = map(lambda x: x.asDict(), SchemaFile.collect())
print(sfDict)
#[{'Column': u'id', 'From': u'1', 'To': u'3'},
# {'Column': u'date', 'From': u'4', 'To': u'8'},
# {'Column': u'name', 'From': u'12', 'To': u'3'},
# {'Column': u'salary', 'From': u'15', 'To': u'5'}]

现在,您可以遍历sfDict中的行,并使用值对列进行子字符串:

from pyspark.sql.functions import substring
File.select(
*[
substring(
str='_c0',
pos=int(row['From']),
len=int(row['To'])
).alias(row['Column']) 
for row in sfDict
]
).show()
#+---+--------+----+------+
#| id|    date|name|salary|
#+---+--------+----+------+
#|001|20181120| xyz| 12341|
#|002|20180203| abc| 56792|
#|003|20181203| pqr| 25483|
#+---+--------+----+------+

请注意,我们必须将ToFrom转换为整数,因为它们在json文件中被指定为字符串。

相关内容

  • 没有找到相关文章

最新更新