【问题标题】:Scala Spark: How do I bootstrap sample from a column of a Spark Dataframe?Scala Spark:如何从 Spark Dataframe 的列中引导样本?
【发布时间】:2020-12-16 15:38:23
【问题描述】:

我希望在集群环境中的 Jupyter Notebook 设置中使用 Scala 编程语言从 Spark DataFrame 的列中采样值并进行替换。我该怎么做?

我尝试了以下在网上找到的功能:

import scala.util

def bootstrapMean(originalData: Array[Double]): Double = {
  val n = originalData.length

  def draw: Double = originalData(util.Random.nextInt(n))

  // a tail recursive loop to randomly draw and add a value to the accumulating sum
  def drawAndSumValues(current: Int, acc: Double = 0D): Double = {
    if (current == 0) acc
    else drawAndSumValues(current - 1, acc + draw)
  }
  drawAndSumValues(n) / n
}

像这样:

val data = stack.select("column_with_values").collect.map(_.toSeq).flatten
val m = 10
val bootstraps = Vector.fill(m)(bootstrapMean(data))

但我得到了错误:

An error was encountered:
<console>:47: error: type mismatch;
 found   : Array[Any]
 required: Array[Double]
Note: Any >: Double, but class Array is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: Double`. (SLS 3.2.10)
       val bootstraps = Vector.fill(m)(bootstrapMean(data))

不知道如何调试它,以及我是否应该打扰或尝试其他方法。我正在寻找想法/文档/代码。谢谢。

更新:

如何将用户 mck 的解决方案放在下面的 for 循环中?我尝试了以下方法:

var bootstrap_container = Seq()
var a = 1
for( a <- 1 until 3){
    var sampled = stack_b.select("diff_hours").sample(withReplacement = true, fraction = 0.5, seed = a)
    var smpl_average = sampled.select(avg("diff_hours")).collect()(0)(0)
    var bootstrap_smpls = bootstrap_container.union(Seq(smpl_average)).collect()
}
bootstrap_smpls

但这会报错:

<console>:49: error: not enough arguments for method collect: (pf: PartialFunction[Any,B])(implicit bf: scala.collection.generic.CanBuildFrom[Seq[Any],B,That])That.
Unspecified value parameter pf.
           var bootstrap_smpls = bootstrap_container.union(Seq(smpl_average)).collect()

【问题讨论】:

    标签: scala apache-spark


    【解决方案1】:

    您可以使用数据帧的sample 方法,例如,如果您想使用替换和0.5 的分数进行采样:

    val sampled = stack.select("column_with_values").sample(true, 0.5)
    

    要获得平均值,您可以这样做:

    val col_average = sampled.select(avg("column_with_values")).collect()(0)(0)
    

    编辑

    var bootstrap_container = List[Double]()
    var a = 1
    for( a <- 1 until 3){
        var sampled = stack_b2.select("diff_hours").sample(withReplacement = true, fraction = 0.5, seed = a)
        var smpl_average = sampled.select(avg("diff_hours")).collect()(0)(0)
        bootstrap_container = bootstrap_container :+ smpl_average.asInstanceOf[Double]
    }
    var mean_bootstrap = bootstrap_container.reduce(_ + _) / bootstrap_container.length
    

    【讨论】:

    • 这有帮助。但是如何将其放入循环中以生成 x 个样本?我认为这将是微不足道的,但最终超出了我目前的能力。
    • @user2205916 你不能把它放到一个for循环中吗?如果你再次调用它,它应该会给你一个不同的样本
    • 怎么样?我更新了我的问题以显示我尝试过的 for 循环代码。
    • 谢谢。我很无奈,显然但是你如何找到bootstrap_container的元素的平均值?此外,更一般地说,Python 有dir(object) 来找出它可以使用的所有函数。 Scala 在 Notebook 环境中的等价物是什么?
    • bootstrap_container.reduce(_ + _) / bootstrap_container.length 会给你平均值。如果您想学习 scala,我建议您阅读文档、阅读教程并搜索您想要在 SO/Google 上实现的目标。
    猜你喜欢
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2019-12-09
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    相关资源
    最近更新 更多