根据分隔符拆分字符串列,并为Pyspark中的每个值创建列

时间:2020-01-25 11:55:29

标签: python pyspark pyspark-sql pyspark-dataframes

我有成千上万的文件,其数据格式如下

a|b|c|clm4=1|clm5=3
a|b|c|clm4=9|clm6=60|clm7=23

我想阅读并将其转换为如下所示的数据框

clm1|clm2|clm3|clm4|clm5|clm6|clm7
a|b|c|1|3|null|null
a|b|c|9|null|60|23

我尝试了以下方法

files = [f for f in glob.glob(pathToFile + "/**/*.txt.gz", recursive=True)]
df = spark.read.load(files, format='csv', sep = '|', header=None)

但这给了我低于结果的结果

clm1, clm2, clm3, clm4, clm5
a, b, c, 1, 3
a, b, c, 9, null

1 个答案:

答案 0 :(得分:1)

对于Spark 2.4+,您可以将文件作为一列读取,然后按RUN npm install -G mysql进行拆分。您将获得一个可以使用higher-order functions进行转换的数组列:

|

我们使用df.show(truncate=False) +----------------------------+ |clm | +----------------------------+ |a|b|c|clm4=1|clm5=3 | |a|b|c|clm4=9|clm6=60|clm7=23| +----------------------------+ 函数将通过将transform列拆分为结构数组而获得的字符串数组进行转换。 每个结构都包含列名(如果存在)(检查字符串是否包含clm)或将其命名为=,其中clm + (i+1)是其位置。

i

现在使用transform_expr = """ transform(split(clm, '[|]'), (x, i) -> struct( IF(x like '%=%', substring_index(x, '=', 1), concat('clm', i+1)), substring_index(x, '=', -1) ) ) """ 将数组转换为map。最后,分解地图并旋转以获取列

map_from_entries

礼物:

df.select("clm", 
          explode(map_from_entries(expr(transform_expr))).alias("col_name", "col_value")
         ) \
  .groupby("clm").pivot('col_name').agg(first('col_value')) \
  .drop("clm") \
  .show(truncate=False)