Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark PySpark groupBy中的中值/分位数_Apache Spark_Pyspark_Apache Spark Sql_Pyspark Sql - Fatal编程技术网

Apache spark PySpark groupBy中的中值/分位数

Apache spark PySpark groupBy中的中值/分位数,apache-spark,pyspark,apache-spark-sql,pyspark-sql,Apache Spark,Pyspark,Apache Spark Sql,Pyspark Sql,我想使用PySpark计算Spark数据帧上的组分位数。无论是近似的还是精确的结果都可以。我更喜欢在groupBy/agg上下文中使用的解决方案,这样我就可以将它与其他PySpark聚合函数混合使用。如果由于某种原因这是不可能的,那么也可以采用不同的方法 相关,但未指示如何将approxQuantile用作聚合函数 我还可以访问percentile_Abrox Hive UDF,但我不知道如何将其用作聚合函数 为了明确起见,假设我有以下数据帧: 从pyspark导入SparkContext 导入

我想使用PySpark计算Spark数据帧上的组分位数。无论是近似的还是精确的结果都可以。我更喜欢在groupBy/agg上下文中使用的解决方案,这样我就可以将它与其他PySpark聚合函数混合使用。如果由于某种原因这是不可能的,那么也可以采用不同的方法

相关,但未指示如何将approxQuantile用作聚合函数

我还可以访问percentile_Abrox Hive UDF,但我不知道如何将其用作聚合函数

为了明确起见,假设我有以下数据帧:

从pyspark导入SparkContext 导入pyspark.sql.f函数 sc=SparkContext df=sc.parallelize[ [A',1], [A',2], [A',3], [B',4], [B',5], [B',6], ].toDF'grp','val' df_grp=df.groupBy'grp'.aggf.magic_百分位数'val',0.5.别名'med_val' df_玻璃钢展 预期结果是:

+----+-------+
| grp|med_val|
+----+-------+
|   A|      2|
|   B|      5|
+----+-------+
由于您可以访问percentile_近似值,一个简单的解决方案是在SQL命令中使用它:

从pyspark.sql导入SQLContext sqlContext=SQLContextsc df.registerTempTabledf df2=sqlContext.sqlselect grp,百分位_approxval,按grp从df组中选择0.5作为中间值 更新:现在这是可能的,请参阅上面接受的答案

不幸的是,据我所知,使用纯PySpark命令似乎不可能做到这一点。Shaido的解决方案提供了一个SQL解决方案,原因非常简单:与其他聚合函数(如均值)相比,approxQuantile不返回列类型,而是返回列表

让我们看一个示例数据:

spark.version u'2.2.0' 将pyspark.sql.functions作为func导入 从pyspark.sql导入DataFrameStatFunctions作为statFunc 平均工程量正常的骨料: df_grp_mean=df.groupBy'grp'。aggfunc.meandf['val']。别名'mean_val' df_grp_平均值显示 +--+----+ |grp |平均值| +--+----+ |B | 5.0| |A | 2.0| +--+----+ 尝试按中位数进行聚合: df_grp_med=df.groupBy'grp'.aggstatfundf.approxQuantile'val',[0.5],0.1 AssertionError:所有表达式都应为列 平均聚合是一列,但中值是一个列表: typefunc.meandf['val'] pyspark.sql.column.column TypeStatFundf.近似分位数'val',[0.5],0.1 列表 我怀疑基于窗口的方法是否会产生任何影响,因为正如我所说,根本原因是一个非常基本的原因


有关更多详细信息,请参见。

我想您不再需要它了。但我会把它留给下一代,也就是下周我忘记的时候

from pyspark.sql import Window
import pyspark.sql.functions as F

grp_window = Window.partitionBy('grp')
magic_percentile = F.expr('percentile_approx(val, 0.5)')

df.withColumn('med_val', magic_percentile.over(grp_window))
或者,为了准确地回答您的问题,这也适用于:

df.groupBy('grp').agg(magic_percentile.alias('med_val'))
作为奖励,您可以通过一系列百分位数:

quantiles = F.expr('percentile_approx(val, array(0.25, 0.5, 0.75))')

您将得到一个列表作为回报。

使用pyspark==2.4.5执行此操作最简单的方法是:

输出:

|grp|50%|
+---+---+
|  B|5.0|
|  A|2.0|
+---+---+

百分位_近似值问题,0.5: 例如,如果范围为[1,2,3,4],此函数返回2作为中值,下面的函数返回2.5:

import statistics

median_udf = F.udf(lambda x: statistics.median(x) if bool(x) else None, DoubleType())

... .groupBy('something').agg(median_udf(F.collect_list(F.col('value'))).alias('median'))

这是可行的,但我更喜欢在PySpark级别的groupBy/agg中使用的解决方案,这样我就可以轻松地将其与其他PySpark聚合函数混合使用。@abeboparebop我不认为只使用groupBy和agg是可行的,但是,使用基于窗口的方法也应该可行。我已经澄清了我在这个问题上的理想解决方案。很明显,这个答案很有用,但它不是我想要的。我会把这个问题留待一段时间,看看是否会有一个更清晰的答案。我认为,在这种情况下,您可以使用底层rdd和计算分布式分位数的算法(例如,以及其中的链接)滚动自己的答案。事实上,他们链接到的github有一些pyspark的例子。非常清晰的答案。你知道如何使用熊猫UDF(也称为矢量化UDF)来实现吗?@CesareIurlaro,我只把它包装在一个UDF中。从来没有试过熊猫,你介意试试吗?性能确实应该在这里大放异彩:使用Spark 3.1.0,现在可以在PySpark groupby聚合中直接使用percentile_近似值:df.groupBykey.aggpercentile_approxvalue,0.5,lit1000000.AliasMiddian@kael或@chris-a我们可以在这个答案中添加00schneider的评论吗?这是最简单和最好的解决方案,因为它内置于pyspark.sql.functions中
import statistics

median_udf = F.udf(lambda x: statistics.median(x) if bool(x) else None, DoubleType())

... .groupBy('something').agg(median_udf(F.collect_list(F.col('value'))).alias('median'))