如何创建一列数组,其值来自一列并且它们的长度来自pyspark数据帧中的另一列?

Posted

技术标签:

【中文标题】如何创建一列数组,其值来自一列并且它们的长度来自pyspark数据帧中的另一列?【英文标题】:How to create a column of arrays whose values are coming from one column and their length is coming from another column in pyspark dataframes? 【发布时间】:2020-08-03 02:09:12 【问题描述】:

在 pyspark 数据框中,我需要创建一个新的 ArrayType(StringType()) 列,其值来自 StringType() 列,它们的长度来自另一个 ArrayType(StringType()) 列的长度。有点像具有动态长度的 array_repeat。

输入

+-------------+-------------+
|col1         |col2         |
+-------------+-------------+
|[1,2]        |‘a’          |
|[1,2,3]      |‘b’          |
+-------------+-------------+

输出

+-------------+-------------+----------------+
|col1         |col2         |col3            |
+-------------+-------------+----------------+
|[1,2]        |‘a’          |['a’,‘a’]       |
|[1,2,3]      |‘b’          |['b’,’b’,’b’]   |
+-------------+----------- -+----------------+

谢谢

【问题讨论】:

【参考方案1】:

另一种选择-

加载提供的测试数据

val df = spark.sql(
      """
        |select col1, col2
        |from values
        | (array(1, 2), 'a'),
        | (array(1, 2, 3), 'b')
        | T(col1, col2)
      """.stripMargin)
    df.show(false)
    df.printSchema()

    /**
      * +---------+----+
      * |col1     |col2|
      * +---------+----+
      * |[1, 2]   |a   |
      * |[1, 2, 3]|b   |
      * +---------+----+
      *
      * root
      * |-- col1: array (nullable = false)
      * |    |-- element: integer (containsNull = false)
      * |-- col2: string (nullable = false)
      */

Alternative-1


    // alternative-1
    df.withColumn("col3", expr("array_repeat(col2, size(col1))"))
      .show(false)

    /**
      * +---------+----+---------+
      * |col1     |col2|col3     |
      * +---------+----+---------+
      * |[1, 2]   |a   |[a, a]   |
      * |[1, 2, 3]|b   |[b, b, b]|
      * +---------+----+---------+
      */

备选方案 2


    // alternative-2
    df.withColumn("col3", expr(s"TRANSFORM(col1, x -> col2)"))
      .show(false)

    /**
      * +---------+----+---------+
      * |col1     |col2|col3     |
      * +---------+----+---------+
      * |[1, 2]   |a   |[a, a]   |
      * |[1, 2, 3]|b   |[b, b, b]|
      * +---------+----+---------+
      */

【讨论】:

【参考方案2】:

使用array_repeat + size

import pyspark.sql.functions as f

df = spark.createDataFrame([[[1,2],'a'], [[1,2,3], 'b']], ['col1', 'col2'])

df.withColumn('col3', f.array_repeat('col2', f.size('col1'))).show()

+---------+----+---------+
|     col1|col2|     col3|
+---------+----+---------+
|   [1, 2]|   a|   [a, a]|
|[1, 2, 3]|   b|[b, b, b]|
+---------+----+---------+

如果在任何情况下这不起作用,您可以编写一个 udf 来执行此操作:

from pyspark.sql.types import StringType, ArrayType
import pyspark.sql.functions as f

@f.udf(ArrayType(StringType()))
def repeat_sizeof(col1, col2):
    return [col1] * len(col2)

df.withColumn('col3', repeat_sizeof('col2', 'col1')).show()

+---------+----+---------+
|     col1|col2|     col3|
+---------+----+---------+
|   [1, 2]|   a|   [a, a]|
|[1, 2, 3]|   b|[b, b, b]|
+---------+----+---------+

【讨论】:

我已经尝试过了,但是我得到了“column is not iterable”错误。 你的 spark 版本是什么?在 spark 3 中测试了这个作品 我在 2.4。谢谢 嗯,我认为它也可以。如果没有,那么您可能需要使用 UDF 执行此操作。

以上是关于如何创建一列数组,其值来自一列并且它们的长度来自pyspark数据帧中的另一列?的主要内容,如果未能解决你的问题,请参考以下文章

通过迭代另一列来创建一列

将行值转换为列,其值来自 spark scala 中的另一列 [重复]

将它们全部单独输出到控制台后,如何创建一组项目?

Presto 数组包含来自另一列的值(超集 SQL 查询)

有没有办法创建一个数组,其值由另一个数组的值决定?

postgresQL 更新列,其值来自正则表达式 + 更多