【问题标题】:Pyspark DataFrame: Split column with multiple values into rowsPyspark DataFrame:将具有多个值的列拆分为行
【发布时间】:2019-11-25 18:04:33
【问题描述】:

我有一个数据框(包含更多行和列),如下所示。

样本 DF:

from pyspark import Row
from pyspark.sql import SQLContext
from pyspark.sql.functions import explode

sqlc = SQLContext(sc)

df = sqlc.createDataFrame([Row(col1 = 'z1', col2 = '[a1, b2, c3]', col3 = 'foo')])
# +------+-------------+------+
# |  col1|         col2|  col3|
# +------+-------------+------+
# |    z1| [a1, b2, c3]|   foo|
# +------+-------------+------+

df
# DataFrame[col1: string, col2: string, col3: string]

我想要什么:

+-----+-----+-----+
| col1| col2| col3|
+-----+-----+-----+
|   z1|   a1|  foo|
|   z1|   b2|  foo|
|   z1|   c3|  foo|
+-----+-----+-----+

我尝试复制此处提供的RDD 解决方案:Pyspark: Split multiple array columns into rows

(df
    .rdd
    .flatMap(lambda row: [(row.col1, col2, row.col3) for col2 in row.col2)])
    .toDF(["col1", "col2", "col3"]))

但是,它没有给出所需的结果

编辑:explode 选项不起作用,因为它当前存储为字符串,而 explode 函数需要一个数组

【问题讨论】:

  • 你在将字符串转换为数组后寻找explode,这可以通过split和regexp_replace来完成。
  • 字符串转数组示例here
  • @pault - explode 将不起作用,因为我的所有列都存储为字符串

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


【解决方案1】:

您可以使用explode,但首先您必须将数组的字符串表示形式转换为数组。

一种方法是使用regexp_replace 删除前导和尾随方括号,然后在", " 上使用split。

from pyspark.sql.functions import col, explode, regexp_replace, split

df.withColumn(
    "col2", 
    explode(split(regexp_replace(col("col2"), "(^\[)|(\]$)", ""), ", "))
).show()
#+----+----+----+
#|col1|col2|col3|
#+----+----+----+
#|  z1|  a1| foo|
#|  z1|  b2| foo|
#|  z1|  c3| foo|
#+----+----+----+

【讨论】:

    【解决方案2】:

    Pault 的解决方案应该可以正常工作,尽管这是另一个使用 regexp_extract 的解决方案(在这种情况下,您实际上不需要替换任何东西)并且它可以处理任意数量的空格:

    from pyspark.sql.functions import col, explode, regexp_extract,regexp_replace, split
    
    df.withColumn("col2", 
                  explode(
                      split(
                          regexp_extract(
                            regexp_replace(col("col2"), "\s", ""), "^\[(.*)\]$", 1), ","))) \
    .show()
    

    说明:

    • 最初regexp_replace(col("col2"), "\s", "") 将用空字符串替换所有空格。
    • 接下来regexp_extract 将提取以[ 开头并以] 结尾的列的内容。
    • 然后我们对逗号分隔值执行split,最后执行explode。

    【讨论】:

    • 在这种情况下您实际上不需要替换任何内容,但您的第一个项目符号是替换空格。您应该能够通过在", +" 上拆分来解决此问题并保持对任意数量空格的支持。
    • 实际上我正在删除空格 pault,我的意思是即使您可以使用 regexp_replace 实现相同的目标,但这里的目标是提取字符串,因此 regexp_exctract 可能更合适。
    • 当然可以,但是如果数组是 [a1, an element with spaces, c3] 呢?只有 OP 可以提供要求——这并不是说你的方法没有用——毕竟它确实适用于给定的测试用例 (+1)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-27
    • 2020-11-10
    • 2020-12-31
    • 1970-01-01
    • 2017-04-22
    相关资源
    最近更新 更多