PySpark根据名称

时间:2017-11-29 11:45:36

标签: python apache-spark pyspark apache-spark-sql

您好,我正在处理稍微困难的文件格式,我试图为将来的处理进行清理。我一直在使用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|
+----------------+---------------------------------+-------------+--------+--------+

因为在那时提取我需要的信息应该是微不足道的。

有没有人对我如何做到这一点有任何建议?

非常感谢。

3 个答案:

答案 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)

您可以使用flatMappivot来实现此目的。从第一阶段的结果开始:

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

进行数据透视的好例子