【问题标题】:How to calculate Percentile of column in a DataFrame in spark?如何计算火花中DataFrame中列的百分比?
【发布时间】:2016-06-06 23:30:32
【问题描述】:

我正在尝试计算 DataFrame 中列的百分位数?我在 Spark 聚合函数中找不到任何 percentile_approx 函数。

例如在 Hive 中,我们有 percentile_approx ,我们可以通过以下方式使用它

hiveContext.sql("select percentile_approx("Open_Rate",0.10) from myTable); 

但出于性能原因,我想使用 Spark DataFrame 来实现。

样本数据集

|User ID|Open_Rate|
------------------- 
|A1     |10.3     |
|B1     |4.04     |
|C1     |21.7     |
|D1     |18.6     |

我想知道有多少用户属于 10% 或 20% 等。我想做这样的事情

df.select($"id",Percentile($"Open_Rate",0.1)).show

【问题讨论】:

  • 使用 SQL 查询和 DataFrame 之间没有性能差异 - 都使用相同的执行引擎。
  • 您可以使用自己的 UDAF。我就是这样做的:stackoverflow.com/a/51859138/2166220

标签: scala apache-spark apache-spark-sql spark-dataframe


【解决方案1】:

从Spark2.0开始,事情变得越来越简单,只需在DataFrameStatFunctions中使用这个函数就好了:

df.stat.approxQuantile("Open_Rate",Array(0.25,0.50,0.75),0.0)

DataFrameStatFunctions 中还有一些对 DataFrame 有用的统计函数。

【讨论】:

  • 很好的发现。我喜欢它允许将相对误差定义为 0 到 1 之间的数字。需要注意的是:此函数不适用于同时对多个组进行聚合计算。对于那些希望一次计算多个组的百分位数的人,请查看percentile_approx,这是一个 spark sql 函数。它将采用与每组观察数相关的整数可选参数:默认为 10,000。这意味着此函数返回少于 10,000 个观测值的组的确切百分位数。指定更大的值以获得更高的精度。
  • 我们需要为 df.stat.approxQuantile 导入什么?
  • @HahaTTpro,仅此而已。对于任何 DataFrame 实例,您都可以使用 dataframeInstance.stat.approxQuantile。
【解决方案2】:

SparkSQL 和 Scala 数据帧/数据集 API 由同一个引擎执行。等价的操作会产生等价的执行计划。你可以通过explain查看执行计划。

sql(...).explain
df.explain

当涉及到您的具体问题时,将 SparkSQL 和 Scala DSL 语法混合使用是一种常见的模式,因为正如您所发现的,它们的功能还不是等效的。 (另一个例子是 SQL 的 explode() 和 DSL 的 explode() 之间的区别,后者更强大但由于编组而效率更低。)

简单的方法如下:

df.registerTempTable("tmp_tbl")
val newDF = sql(/* do something with tmp_tbl */)
// Continue using newDF with Scala DSL

如果您使用简单的方法,您需要记住的是临时表名称是集群全局的(最高 1.6.x)。因此,如果代码可能在同一个集群上同时运行多次,您应该使用随机表名。

在我的团队中,这种模式很常见,我们在DataFrame 中添加了一个隐含的.sql(),它会自动为 SQL 语句的范围注册然后取消注册一个临时表。

【讨论】:

  • 你是对的。并感谢您的详细解释。但是我想在数据框中执行此操作的原因是因为我几乎没有其他方法和需要应用的 UDF。如果我要使用普通的 sql/hive,我将不得不更改很多代码来实现这个百分位数。也不确定如果我更改代码可能会出现什么其他问题。
  • @dheee 我不确定我是否理解您的担忧... (1) 您可以在 SQL 和 DSL 中使用自己的 UDF。 (2) 您不需要更改所有代码,只需更改生成带有百分位数的列的阶段。
【解决方案3】:

我创建了一个bebe 库,可以轻松计算列的百分位数。

让我们从创建 DataFrame 开始。

val df = spark
  .createDF(
    List(
      ("A1", 10.3),
      ("B1", 4.04),
      ("C1", 21.7),
      ("D1", 18.6)
    ),
    List(
      ("User ID", StringType, true),
      ("Open_Rate", DoubleType, true)
    )
  )
df.show()
+-------+---------+
|User ID|Open_Rate|
+-------+---------+
|     A1|     10.3|
|     B1|     4.04|
|     C1|     21.7|
|     D1|     18.6|
+-------+---------+

现在让我们计算第 10 个百分位数:

val resDF = df.agg(bebe_percentile(col("Open_Rate"), lit(0.1)).as("10_percentile"))
resDF.show()
+-----------------+
|    10_percentile|
+-----------------+
|5.918000000000001|
+-----------------+

它使用与the SQL percentile method相同的底层代码。

【讨论】:

    猜你喜欢
    • 2018-11-22
    • 2017-03-28
    • 2018-10-16
    • 2016-12-02
    • 2020-12-25
    • 2022-01-14
    • 2020-10-20
    • 1970-01-01
    相关资源
    最近更新 更多