计算并比较两列的平均值

velaa5lx  于 2021-07-13  发布在  Spark
关注(0)|答案(1)|浏览(593)

我开始将我的pandas实现转换为pyspark,但在执行一些基本操作时遇到了问题。我有一张table:

+-----+-----+----+
| Col1|Col2 |Col3|
+-----+-----+----+
|  1  |[1,3]|   0|
|  44 |[2,0]|   1|
|  77 |[1,5]|   7|
+-----+-----+----+

我想要的输出是:

+-----+-----+----+----+
| Col1|Col2 |Col3|Col4|
+-----+-----+----+----+
|  1  |[1,3]|   0|2.67|
|  44 |[2,0]|   1|2.67|
|  77 |[1,5]|   7|2.67|
+-----+-----+----+----+

要到达这里:
我对col2中每个数组的第一项求平均值,对col2中每个数组的第二项求平均值。因为第二个“子栏”的平均值比第一个“子栏”((1+2+1)/3)大((3+0+5)/3),这就是“获胜”条件。之后,我创建了一个新列,该列的“获胜”平均值复制了该表的行数(在本例中为3)。我已经能够通过“手动”选择ta列来实现这一点,对其进行平均,然后使用“lit”来复制结果。我的实现的问题是collect()需要花费很多时间,而且不建议这样做。你能帮我做这个吗?

gj3fmq9x

gj3fmq9x1#

你可以用 greatest 要获取数组中每个(子)列的最大平均值,请执行以下操作:

from pyspark.sql import functions as F, Window

df2 = df.withColumn(
    'Col4',
    F.greatest(*[F.avg(F.udf(lambda r: [float(i) for i in r.toArray()], 'array<double>')('Col2')[i]).over(Window.orderBy()) for i in range(2)])
)

df2.show()
+----+------+----+------------------+
|Col1|  Col2|Col3|              Col4|
+----+------+----+------------------+
|   1|[1, 3]|   0|2.6666666666666665|
|  44|[2, 0]|   1|2.6666666666666665|
|  77|[1, 5]|   7|2.6666666666666665|
+----+------+----+------------------+

如果希望数组大小是动态的,可以这样做

arr_size = df.select(F.max(F.size(F.udf(lambda r: [float(i) for i in r.toArray()], 'array<double>')('Col2')))).head()[0]

df2 = df.withColumn(
    'Col4',
    F.greatest(*[F.avg(F.udf(lambda r: [float(i) for i in r.toArray()], 'array<double>')('Col2')[i]).over(Window.orderBy()) for i in range(arr_size)])
)

相关问题