如何使用 Spark 查找中位数和分位数

2024-03-04

我怎样才能找到一个中位数RDD使用分布式方法、IPython 和 Spark 计算整数?这RDD大约有 700,000 个元素,因此太大而无法收集和查找中位数。

这个问题与这个问题类似:如何使用 Apache Spark 计算精确中位数? https://stackoverflow.com/questions/28158729/how-can-i-calculate-exact-median-with-apache-spark。然而,问题的答案是在 Scala 中,我不知道。

使用 Scala 答案的想法,我尝试用 Python 编写一个类似的解决方案。

我知道我首先要排序RDD。我不知道怎么。我看到sortBy(按给定的值对该 RDD 进行排序keyfunc) and sortByKey(对此进行排序RDD,假设由(键,值)对组成。)方法。我认为两者都使用键值和我的RDD仅具有整数元素。

  1. 首先,我想做myrdd.sortBy(lambda x: x)?
  2. 接下来我将找到 rdd 的长度(rdd.count()).
  3. 最后,我想找到 RDD 中心的一个或 2 个元素。我也需要这个方法的帮助。

EDIT:

我有一个主意。也许我可以索引我的RDD然后键=索引和值=元素。然后我可以尝试按值排序吗?我不知道这是否可能,因为只有一个sortByKey method.


正在进行的工作

SPARK-30569 https://issues.apache.org/jira/browse/SPARK-30569 - 添加调用percentile_approx 的DSL 函数

火花2.0+:

您可以使用approxQuantile实现的方法格林沃尔德-卡纳算法 http://infolab.stanford.edu/~datar/courses/cs361a/papers/quantiles.pdf:

Python:

df.approxQuantile("x", [0.5], 0.25)

Scala:

df.stat.approxQuantile("x", Array(0.5), 0.25)

其中最后一个参数是相对误差。数字越低,结果越准确,计算成本也越高。

从 Spark 2.2 开始(SPARK-14352 https://issues.apache.org/jira/browse/SPARK-14352)它支持对多列进行估计:

df.approxQuantile(["x", "y", "z"], [0.5], 0.25)

and

df.approxQuantile(Array("x", "y", "z"), Array(0.5), 0.25)

底层方法也可用于 SQL 聚合(全局和摸索):approx_percentile https://spark.apache.org/docs/latest/api/sql/index.html#approx_percentile功能:

> SELECT approx_percentile(10.0, array(0.5, 0.4, 0.1), 100);
 [10.0,10.0,10.0]
> SELECT approx_percentile(10.0, 0.5, 100);
 10.0

火花

Python

正如我在评论中提到的,这很可能不值得大惊小怪。如果数据相对较小(就像您的情况一样),则只需在本地收集并计算中位数:

import numpy as np

np.random.seed(323)
rdd = sc.parallelize(np.random.randint(1000000, size=700000))

%time np.median(rdd.collect())
np.array(rdd.collect()).nbytes

在我几年前的电脑和大约 5.5MB 内存上,大约需要 0.01 秒。

如果数据很大,排序将成为一个限制因素,因此与其获取精确值,不如在本地采样、收集和计算。但如果你真的想使用 Spark,这样的东西应该可以解决问题(如果我没有搞砸任何事情):

from numpy import floor
import time

def quantile(rdd, p, sample=None, seed=None):
    """Compute a quantile of order p ∈ [0, 1]
    :rdd a numeric rdd
    :p quantile(between 0 and 1)
    :sample fraction of and rdd to use. If not provided we use a whole dataset
    :seed random number generator seed to be used with sample
    """
    assert 0 <= p <= 1
    assert sample is None or 0 < sample <= 1

    seed = seed if seed is not None else time.time()
    rdd = rdd if sample is None else rdd.sample(False, sample, seed)

    rddSortedWithIndex = (rdd.
        sortBy(lambda x: x).
        zipWithIndex().
        map(lambda (x, i): (i, x)).
        cache())

    n = rddSortedWithIndex.count()
    h = (n - 1) * p

    rddX, rddXPlusOne = (
        rddSortedWithIndex.lookup(x)[0]
        for x in int(floor(h)) + np.array([0L, 1L]))

    return rddX + (h - floor(h)) * (rddXPlusOne - rddX)

和一些测试:

np.median(rdd.collect()), quantile(rdd, 0.5)
## (500184.5, 500184.5)
np.percentile(rdd.collect(), 25), quantile(rdd, 0.25)
## (250506.75, 250506.75)
np.percentile(rdd.collect(), 75), quantile(rdd, 0.75)
(750069.25, 750069.25)

最后让我们定义中位数:

from functools import partial
median = partial(quantile, p=0.5)

到目前为止还不错,但在没有任何网络通信的本地模式下需要 4.66 秒。可能有办法改善这一点,但为什么还要麻烦呢?

独立于语言 (蜂巢UDAF):

如果你使用HiveContext您还可以使用 Hive UDAF。具有整数值:

rdd.map(lambda x: (float(x), )).toDF(["x"]).registerTempTable("df")

sqlContext.sql("SELECT percentile_approx(x, 0.5) FROM df")

对于连续值:

sqlContext.sql("SELECT percentile(x, 0.5) FROM df")

In percentile_approx您可以传递一个附加参数来确定要使用的记录数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Spark 查找中位数和分位数 的相关文章

随机推荐

  • 让 jquery ajaxStop 每次只触发一次

    由于某种原因 我的 ajaxStop 代码现在触发了两次 我需要将其限制为一次 submit bind click function e fileupload ajaxForm target status submit document a
  • 是否可以使用 ggplot 在地图上覆盖散点图?

    我想画一张法国省份 即法国的地区 的地图以及地图上的标绘点 我使用 ggplot2 绘制地图 但是当我想在地图上添加点时 R 返回一个错误 指出它找不到 组 library ggplot2 library ggmap load the co
  • 实体框架未将更改保存到数据库中

    我很困惑为什么这段代码不起作用 它应该在循环后保存对数据库的更改 但是当我放置SaveChanges循环内的方法 它将记录保存到数据库中 但在循环外不保存任何内容 大概只有300 1000条记录 static bool lisReady f
  • Fragment中的Toast,应该使用getActivity()还是getAcitivity().getApplicationContext()?

    抱歉我的新手问题 我只是无法从谷歌和stackoverflow找到答案 我刚刚开始学习android 希望能为android知识打下良好的基础 我想知道如果我在片段中创建 toast maketext 我应该在下面使用哪个 getActiv
  • 从无状态 EJB 访问 SessionScoped 对象

    我确实有一个 SessionScoped 课程 对于每个用户访问 我需要一个此类的自己的实例 很长一段时间一切都很顺利 但现在我还需要从后端访问这些对象 而无需任何用户交互 我确实有一个无状态企业 bean 但每当我想访问会话范围对象时 我
  • 使用 EF Core 7 的 .NET 7 控制台应用程序为什么没有 OnConfiguring?

    我首先构建了数据库 NET 7 和 EF Core 7 应用程序 并使用 EF Power Tools 创建上下文和模型类 我继续阅读有关OnConfiguring 在上下文类中 我只有OnModelCreating 我做错了什么 谢谢 道
  • Clojure:转换 Varargs 但保留 Varargs

    我正在用 Clojure 开发一个小宠物项目 我有一个传递可变参数的函数 defn foor bar args let new args custom transform args do something new args But do
  • 从 UITapGestureRecognizer 中删除目标

    我已将操作作为匿名方法添加到我的手势识别器中 UITapGestureRecognizer tapGesture new UITapGestureRecognizer tapGesture AddTarget gt HandleTap ta
  • .Net Core 3.0 Nginx 不提供静态文件

    我有一个 net core 3 0 Web 应用程序 我想在 Debian Buster 服务上运行 我按照微软的说明进行操作发现Here https learn microsoft com en us aspnet core host a
  • 特定递归函数的增长顺序

    以下函数的增长顺序是什么 static int counter 0 static void Example int n if n 1 return for int i 0 i lt n i counter Example n 2 为了解决这
  • 如何在给定的绘图上绘制垂直线

    给定时间表示中的信号图 如何绘制标记相应时间索引的线 具体来说 给定一个时间索引范围从 0 到 2 6 秒 的信号图 我想绘制垂直红线来指示列表的相应时间索引 0 22058956 0 33088437 2 20589566 我该怎么做 添
  • 如何检查Google用户的图片是默认的还是上传的?

    如何检查用户的个人资料图片是默认的还是上传到 Google 的 Note 当您从 API 获取用户详细信息时 所有默认个人资料图片都有以下 URL https lh3 googleusercontent com XdUIqdMkCWA AA
  • 适用于 Safari 浏览器的类似 Firebug 的插件

    Safari 是否有一个开发工具插件 就像 Firefox 的 Firebug 插件一样 Firebug 很棒 但 Safari 提供了自己的内置开发工具 如果您还没有尝试过 Safari 的开发工具包 请转到 Safari gt 首选项
  • Vim 的 Clang 完整版

    我复制了clang complete vim插件 但是当我输入 在一些变量之后 它说 未找到模式 我搜索了这个问题 有人说我应该配置g clang complete auto and g clang complete copen 我怎样才能
  • Swift 从对象数组映射到异步函数数组并等待它们全部

    我刚刚更新到 Xcode 13 2 1 现在可以访问异步等待 并且我正在尝试找到可以从合并 转换 为异步等待的地方 我想实现以下目标 给定一个像 的类型 struct Person let name String func fetchAva
  • React Native 地图:在react-native-maps 中使用自定义标记时,标记图像不显示

    我在用着react native maps但我遇到了一个问题 经过大量谷歌搜索后没有答案让我在这里问它 我正在尝试使用自定义标记作为地图中的标记 如下图所示 当我搜索时我发现需要使用自定义标记来完成创客的设计 然后我创建了一个自定义标记组件
  • 如何将 Jsoup(Java html 解析器)中生成的文档转换为字符串

    我有一个用 jsoup 制作的文档 如下所示 Document doc Jsoup connect http en wikipedia org get 我该如何转换它doc成字符串 你有没有尝试过 Document doc Jsoup co
  • JavaFX RotateTransition 无限期停止

    下面代码的问题在于两个动画之间有大约半秒的暂停 我希望节点不断旋转 RotateTransition rt new RotateTransition Duration seconds 2 syncNode rt setFromAngle 0
  • 如何停止反应原生动画

    我试图在本机反应中停止动画 但它不起作用 我尝试这样做停止动画方法 https facebook github io react native docs animated html stopanimation 这是我的代码 construc
  • 如何使用 Spark 查找中位数和分位数

    我怎样才能找到一个中位数RDD使用分布式方法 IPython 和 Spark 计算整数 这RDD大约有 700 000 个元素 因此太大而无法收集和查找中位数 这个问题与这个问题类似 如何使用 Apache Spark 计算精确中位数 ht