Scala Spark Sample 和 SampleBy 具有相同的行为

问题描述 投票:0回答:2

我正在尝试在 Spark Dataframe 中执行分层采样,但 SampleBy 函数的行为(奇怪地)与 Sample 类似。

Spark版本3.0.1

import spark.implicits._

val data = Seq( ("Java", 20000), ("Java", 10000), ("Java", 3000),  ("Java", 17000),
                ("Python", 100000), ("Python", 20000),
                ("Scala", 3000), ("Scala", 4000), ("Scala", 1000), ("Scala", 43000), ("Scala", 2000), ("Scala", 9000)).toDF("Language", "Price")
val sample_size = 0.5
val seed = 762387
val stratify = "Language"

val subsample = data.sample(withReplacement=false, fraction=sample_size, seed=seed)

subsample.show()

val fractions = data.select(stratify).distinct().as[String].collect().map((_, sample_size)).toMap
println(fractions.mkString("\n")
val stratified_subsample = data.stat.sampleBy(stratify, fractions=fractions, seed=seed)

stratified_subsample.show()

输出:

+--------+------+
|Language| Price|
+--------+------+
|    Java|  3000|
|  Python|100000|
|  Python| 20000|
|   Scala|  3000|
|   Scala| 43000|
|   Scala|  2000|
|   Scala|  9000|
+--------+------+

Scala -> 0.5
Python -> 0.5
Java -> 0.5

+--------+------+
|Language| Price|
+--------+------+
|    Java|  3000|
|  Python|100000|
|  Python| 20000|
|   Scala|  3000|
|   Scala| 43000|
|   Scala|  2000|
|   Scala|  9000|
+--------+------+

用另一个种子输出(6354345):

+--------+------+
|Language| Price|
+--------+------+
|    Java| 10000|
|    Java| 17000|
|  Python|100000|
|   Scala|  3000|
|   Scala|  4000|
|   Scala|  1000|
|   Scala| 43000|
|   Scala|  2000|
|   Scala|  9000|
+--------+------+

Scala -> 0.5
Python -> 0.5
Java -> 0.5

+--------+------+
|Language| Price|
+--------+------+
|    Java| 10000|
|    Java| 17000|
|  Python|100000|
|   Scala|  3000|
|   Scala|  4000|
|   Scala|  1000|
|   Scala| 43000|
|   Scala|  2000|
|   Scala|  9000|
+--------+------+

我尝试过不同的数据帧、不同的种子,并且两个数据帧始终相等。我总是有同样的行为,样本根本没有分层。我知道 SampleBy 并不准确,但具有相同的行为似乎不太好。我的片段有问题吗?

scala dataframe apache-spark sampling
2个回答
0
投票

这是预期的结果。

sampleBy
fraction
参数中期望每个层的采样分数。如果所有采样分数都相同,则结果与简单的
sample
相同。

示例:

sample(fractions = 0.5)
的意思是:请从我的原始数据集中随机抽取行,以便结果的大小大约为原始数据集的一半。

sampleBy(..., Map('Scala' -> 0.5, 'Python' -> 0.5, 'Java' -> 0.5))
的意思是:请用
Scala
取一半行+用
Python
取一半行+用
Java
取一半行。结果(大约)与第一种情况相同。

需要注意的一件事是 sampleBy 使用 udf,我预计

sampleBy
会比
sample
慢得多。


-1
投票

当您使用“种子”时,您将获得相同的样本。如果你填为0那么每次运行都会得到不同的样本

© www.soinside.com 2019 - 2024. All rights reserved.