【问题标题】:Spark DataFrame - Select n random rowsSpark DataFrame - 选择 n 个随机行
【发布时间】:2017-01-13 15:52:10
【问题描述】:

我有一个包含数千条记录的数据框,我想随机选择 1000 行到另一个数据框中进行演示。我怎样才能在 Java 中做到这一点?

谢谢!

【问题讨论】:

  • 您是否已经尝试使用 Spark SQL 使用 HiveQL 查询?
  • 是的,但我没有看到相关性。
  • @Umberto 请记住,问题是关于获取 n 个随机行,而不是 n 个前行。这个问题的作者可以实现自己的采样或使用 Spark 中实现的一种可能性
  • @T.Gawęda 我知道,但是使用 HiveQL(Spark SQL 旨在与 Hive 兼容)您可以创建一个选择语句,以有效的方式随机选择 n 行,并且您可以使用那。为什么不?这是另一种方式
  • @Umberto 你能发布这样的代码吗?这听起来不错!但请记住,LIMIT 不会返回随机结果,请参阅stackoverflow.com/questions/23802115/…

标签: java apache-spark dataframe


【解决方案1】:

我更喜欢 pyspark 中的这个

df.sample(withReplacement=False, fraction=desired_fraction)

这里是doc

【讨论】:

  • 这并没有给出你想要采样的确切数字,这真的是出乎意料的。
【解决方案2】:

你可以洗牌,然后取最上面的:

import org.apache.spark.sql.functions.rand

dataset.orderBy(rand()).limit(n)

【讨论】:

  • 这个实现效率高吗? Order by 的费用是多少?
  • 非常简单但效率极低。如果您很高兴拥有粗略的行数,最好使用过滤器而不是分数,而不是填充和排序整个随机向量以获得n 最小值
【解决方案3】:

你可以试试 sample() 方法。不幸的是,您必须给出的不是数字,而是分数。你可以这样写函数:

def getRandom (dataset : Dataset[_], n : Int) = {
    val count = dataset.count();
    val howManyTake = if (count > n) n else count;
    dataset.sample(0, 1.0*howManyTake/count).limit (n)
}

说明: 我们必须获取一小部分数据。如果我们有 2000 行,而您想获得 100 行,那么总行数必须为 0.5。如果你想得到比 DataFrame 中更多的行,你必须得到 1.0.0。 调用 limit() 函数以确保舍入正常,并且您没有得到比您指定的更多的行数。

编辑:我在其他答案中看到了 takeSample 方法。但请记住:

  1. 这是一种 RDD 方法,而不是 Dataset,所以你必须这样做: dataset.rdd.takeSample(0, 1000, System.currentTimeMilis()).toDF() takeSample 将收集所有值。
  2. 请记住,如果您想获取很多行,那么您将遇到 OutOfMemoryError 问题,因为 takeSample 正在驱动程序中收集结果。谨慎使用

【讨论】:

  • 有没有办法在不计算数据帧的情况下做到这一点,因为这个操作在大型 DF 中成本太高。
  • @Hasson 尝试缓存DataFrame,这样第二个动作会快很多。或者你也可以使用 approxQuantile 函数,它会更快但不太精确
  • 提供一些保证金可能会有所帮助。 df.sample(math.min(1.0, 1.1 * howManyTake / count)).limit(n)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-25
  • 1970-01-01
  • 2016-06-17
相关资源
最近更新 更多