Pyspark DataFrame:将包含多个值的列拆分为行

5
我有一个数据框(具有更多的行和列),如下所示。
样本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”函数需要一个数组。

在将字符串转换为数组后,您需要使用splitregexp_replace来查找explode - pault
如何将字符串转换为数组的示例在这里 - pault
@pault - 因为我的所有列都存储为字符串,所以explode无法使用。 - SmitM
2个回答

4
您可以使用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
保罗的解决方案应该完美地工作,尽管这里有另一个解决方案,它使用regexp_extract(在这种情况下你不需要替换任何东西),并且可以处理任意数量的空格: "保罗的解决方案应该完美地工作,尽管这里有另一个解决方案,它使用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
实际上我是在去除空格,pault,我的意思是即使你可以用regexp_replace实现相同的效果,这里的目标是提取一个字符串,因此regexp_extract可能更合适。 - abiratsis
1
当然,但如果数组是 [a1,一个带有空格的元素,c3] 呢?只有 OP 可以提供要求 - 这并不意味着您的方法没有用 - 毕竟它对于给定的测试用例有效(+1)。 - pault

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接