【问题标题】:randomly initialized dataframe in sparkspark中随机初始化的数据帧
【发布时间】:2019-08-10 03:15:46
【问题描述】:

我需要创建一个包含 n 行的数据框,并且一行的每一列值随机初始化为 0/1。一个示例数据框是:

+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  1 |  0 |  1 |
|  2 |  1 |  1 |
|  3 |  1 |  0 |
+----+----+----+

目前我正在使用以下程序:

  • 创建空数据框
  • 生成单个序列
  • 使用 union() 附加到现有数据帧

代码如下:

for (k <- 0 until n) { 
  var newRow = k+:Seq.fill(N)(Random.nextInt(2)) // random fill with 0/1 and appending id
  X = X.union(newRow.toDF())
}

上述方法会影响性能(运行时间)吗?有没有更好的方法来做到这一点?

【问题讨论】:

  • 联合是昂贵的。您可以创建一个列表,然后将列表转换为数据框(对不起,不是 Scala 专家 :()

标签: scala apache-spark for-loop functional-programming apache-spark-sql


【解决方案1】:

有一个隐式方法可以在 scala 中从 Iterable 创建 DataFrame,你可以利用它提供的,它由元组组成。以下代码:

val a = (for (_ <- 0 until 5) yield Seq.fill(3)(Random.nextInt(2)))
    .map(x => (x(0), x(1), x(2)))
import spark.implicits._
a.toDF.show

给出以下结果:

+---+---+---+
| _1| _2| _3|
+---+---+---+
|  0|  1|  1|
|  1|  0|  0|
|  0|  0|  0|
|  0|  1|  0|
|  1|  1|  1|
+---+---+---+

您可以正确地提供架构/重命名列。有关为什么这些内部结构必须是元组的更多信息,请参阅answer

【讨论】:

  • 假设要转换的迭代太大而无法存储在驱动程序中。还有其他方法可以创建数据框吗?
【解决方案2】:

上述方法会影响性能(运行时间)吗?

在很多方面,但主要是由于不断增长的血统和执行计划。此外,在本地序列上调用 toDF 会将所有数据保存在驱动程序的内存中。

换句话说 - 它根本无法扩展。

有没有更好的方法来做到这一点?

当然有:

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

spark.range(n).select(
  $"id" + 1 as "id", 
  (rand() > 0.5) cast("integer") as "c1", (rand() > 0.5) cast("integer") as "c2")

【讨论】:

  • 感谢您的回答。这就是我想要的,但我需要将它推广到可变数量的列(假设 x 列的名称为 _c1 到 _cx)。我们如何处理这个要求?
猜你喜欢
  • 2017-03-10
  • 1970-01-01
  • 1970-01-01
  • 2018-03-25
  • 2018-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多