您好,我正在处理稍微困难的文件格式,我试图为将来的处理进行清理。我一直在使用Pyspark将数据处理成数据帧。
该文件与此类似:
AA 1234 ZXYW
BB A 890
CC B 321
AA 1234 LMNO
BB D 123
CC E 321
AA 1234 ZXYW
CC E 456
每个' AA' record定义一个或多个逻辑组的开始,每行上的数据是固定长度,并且包含我想要提取的信息。至少有20-30种不同的记录类型。它们始终在每行的开头用两个字母代码标识。每组中可以有1种或多种不同的记录类型(即并非所有记录类型都存在于每个组中)
作为第一阶段,我设法以这种格式将记录分组:
+----------------+---------------------------------+
| index| result|
+----------------+---------------------------------+
| 1|[AA 1234 ZXYV,BB A 890,CC B 321]|
| 2|[AA 1234 LMNO,BB D 123,CC E 321]|
| 3|[AA 1234 ZXYV,CC B 321] |
+----------------+---------------------------------+
作为第二阶段,我真的希望将数据放入数据帧的以下列中:
+----------------+---------------------------------+-------------+--------+--------+
| index| result| AA| BB| CC|
+----------------+---------------------------------+-------------+--------+--------+
| 1|[AA 1234 ZXYV,BB A 890,CC B 321]|AA 1234 ZXYV|BB A 890|CC B 321|
| 2|[AA 1234 LMNO,BB D 123,CC E 321]|AA 1234 LMNO|BB D 123|CC E 321|
| 3|[AA 1234 ZXYV,CC B 321] |AA 1234 ZXYV| Null|CC B 321|
+----------------+---------------------------------+-------------+--------+--------+
因为在那时提取我需要的信息应该是微不足道的。
有没有人对我如何做到这一点有任何建议?
非常感谢。
答案 0 :(得分:5)
在不转换为rdd的情况下爆炸数组的替代方法,
from pyspark.sql import functions as F
udf1 = F.udf(lambda x : x.split()[0])
df.select('index',F.explode('result').alias('id'),udf1(F.col('id')).alias('idtype')).show()
+-----+-------------+------+
|index| id|idtype|
+-----+-------------+------+
| 1|AA 1234 ZXYV| AA|
| 1| BB A 890| BB|
| 1| CC B 321| CC|
| 2|AA 1234 LMNO| AA|
| 2| BB D 123| BB|
| 2| CC E 321| CC|
| 3|AA 1234 ZXYV| AA|
| 3| CC B 321| CC|
+-----+-------------+------+
df1.groupby('index').pivot('idtype').agg(F.first('id')).join(df,'index').show()
答案 1 :(得分:1)
您可以使用flatMap
和pivot
来实现此目的。从第一阶段的结果开始:
rdd = sc.parallelize([(1,['AA 1234 ZXYV','BB A 890','CC B 321']),
(2,['AA 1234 LMNO','BB D 123','CC E 321']),
(3,['AA 1234 ZXYV','CC B 321'])])
df = rdd.toDF(['index', 'result'])
您可以先使用flatMap
将数组分解为多行,然后将两个字母的标识符提取到一个单独的列中。
df_flattened = df.rdd.flatMap(lambda x: [(x[0],y, y[0:2],y[3::]) for y in x[1]])\
.toDF(['index','result', 'identifier','identifiertype'])
并使用pivot
将双字母标识符更改为列名:
df_result = df_flattened.groupby(df_flattened.index,)\
.pivot("identifier")\
.agg(first("identifiertype"))\
.join(df,'index')
我添加了联接以获取result
列
答案 2 :(得分:0)
假设您正在使用Spark 2.x,我认为您正在寻找的是对spark数据帧的透视操作。
首先,你可以创建一个只有2列的表,2个字母的编码和其他列的内容。然后,您可以在数据框上使用pivot来执行此操作,如下所示。
df.pivot("encoding_col",Seq("AA","BB"))
您可以找到一些使用数据框Rename Files Based On Folder Name
进行数据透视的好例子