我认为@Ahmed 的udf 回答是最好的方法,但这里有另一种方法,对于小型n 可能同样好或更好:
首先,在整个DataFrame上收集n的最大值:
max_n = df.select(f.max('n').alias('max_n')).first()['max_n']
print(max_n)
#3
现在为长度为max_n 的每一行创建一个数组,其中包含range(max_n) 中的数字。此中间步骤的输出将产生一个 DataFrame,如下所示:
df.withColumn('n_array', f.array([f.lit(i) for i in range(max_n)])).show()
#+---+---+---+---------+
#| A| B| n| n_array|
#+---+---+---+---------+
#| 1| 2| 1|[0, 1, 2]|
#| 2| 9| 1|[0, 1, 2]|
#| 3| 8| 2|[0, 1, 2]|
#| 4| 1| 1|[0, 1, 2]|
#| 5| 3| 3|[0, 1, 2]|
#+---+---+---+---------+
现在我们分解n_array 列,并过滤以仅保留数组中小于n 的值。这将确保我们拥有每行的n 副本。最后我们删除分解后的列得到最终结果:
df.withColumn('n_array', f.array([f.lit(i) for i in range(max_n)]))\
.select('A', 'B', 'n', f.explode('n_array').alias('col'))\
.where(f.col('col') < f.col('n'))\
.drop('col')\
.show()
#+---+---+---+
#| A| B| n|
#+---+---+---+
#| 1| 2| 1|
#| 2| 9| 1|
#| 3| 8| 2|
#| 3| 8| 2|
#| 4| 1| 1|
#| 5| 3| 3|
#| 5| 3| 3|
#| 5| 3| 3|
#+---+---+---+
但是,我们正在为每一行创建一个 max_n 长度数组,而不是 udf 解决方案中的一个 n 长度数组。我目前还不清楚这将如何扩展与 udf 对于大型 max_n,但我怀疑 udf 会胜出。