从集合中随机替换 spark 数据集列值

Posted

技术标签:

【中文标题】从集合中随机替换 spark 数据集列值【英文标题】:replacing spark dataset column values randomly from a set 【发布时间】:2017-11-21 06:23:24 【问题描述】:

有一个数据集 imputedcsv,我想将 Gender 列中的空值随机替换为 Male 或 Female..

imputedcsv.groupBy("Gender").count.show()

+------+-----+
|Gender|count|
+------+-----+
|  null|   24|
|Female|  240|
|  Male|  242|
+------+-----+

一个用单个值填充空值,但是如何从一组值中随机填充列的空值说Male,Female

imputedcsv.na.fill("Male", Seq("Gender")).groupBy("Gender").count.show()

+------+-----+
|Gender|count|
+------+-----+
|Female|  240|
|  Male|  266|
+------+-----+

我需要用MaleFemale 随机填充它,而不是只用一个值Male 替换空值。

类似于使用sample(c('Male','Female'))

对于单个值,我们有 How to replace null values with a specific value in Dataframe using spark in Java?

感谢任何帮助。

【问题讨论】:

【参考方案1】:

如果您认为 Gender 是 FemaleMale 的概率相等,您可以这样做:

df.withColumn( "gender", 
    coalesce($"gender", 
                 when(round(rand).cast("int") === lit(0) , lit("Male") )
                 .otherwise(lit("Female"))
             )).show

coalesce 使其仅适用于 null 值。 round(rand).cast("int") 每次都会生成01,然后MaleFemale 将由when - otherwise 构造决定。

【讨论】:

似乎 df.na.fill 只取一个值...所以对于不同的运行,我们会随机获得男性或女性,,,,但是一旦获得一个值..该值用于填满所有的 NAs.. val r = new scala.util.Random val genderMap = Map(1 -> "Female", 0 -> "Male") val newdf1=imputedcsv.na.fill(genderMap.getOrElse(Math .round(r.nextFloat) , "Female" ) ) newdf1.groupBy("Gender").count.show() 结果:Run1:男性 242 女性 264 Run2:男性:266 女性:240 它有效..谢谢..任何指针..关于合并如何使其仅适用于空值的解释.. coalesce 是一个预定义的函数,它采用任意数量的列。假设如果一个查询被定义为coalesce(a, "Hello"),那么它将返回Hello,只要a 是NULL,否则它将返回列a 的原始值。请接受答案,以便将问题标记为已解决。谢谢。 谢谢。接受了答案。祝你有美好的一天!【参考方案2】:

您可以使用when & otherwisewithColumn 来实现它,如下所示:

scala> df.groupBy("Gender").count.show

+------+-----+
|Gender|count|
+------+-----+
|  null|    2|
|female|    4|
|  male|    4|
+------+-----+

scala> df.withColumn("gender", when(($"gender".isNull), "male").otherwise($"gender")).groupBy("gender").count.show
+------+-----+
|gender|count|
+------+-----+
|female|    4|
|  male|    6|
+------+-----+

我错过了randomly,你可以像下面这样实现它:

scala> val gender_set = Set("male","female")
gender_set: scala.collection.immutable.Set[String] = Set(male, female)

scala> import scala.util.Random
import scala.util.Random

scala>  val rnd=new Random
rnd: scala.util.Random = scala.util.Random@668b5a55

scala> df.withColumn("gender", when(($"gender".isNull), gender_set.toVector(rnd.nextInt(gender_set.size))).otherwise($"gender")).groupBy("gender").count.show
+------+-----+
|gender|count|
+------+-----+
|female|    4|
|  male|    6|
+------+-----+


scala> df.withColumn("gender", when(($"gender".isNull), gender_set.toVector(rnd.nextInt(gender_set.size))).otherwise($"gender")).groupBy("gender").count.show
+------+-----+
|gender|count|
+------+-----+
|female|    6|
|  male|    4|
+------+-----+

谢谢。

【讨论】:

如果你想在你的 sn-p 中使用单个值..“男性”,上面的内容很好。我正在探索从“男性”或“女性”中分配一个随机值。【参考方案3】:

我需要将 @Learner 的代码放入 UDF 中才能工作,否则会出错。

df.groupBy($"Gender").count.show()
+------+-----+
|Gender|count|
+------+-----+
|  null|    3|
|Female|    3|
|  Male|    2|
+------+-----+
val gender_set = Set("Male","Female")

val randGenderUDF = udf(() => 
   gender_set.toVector(rnd.nextInt(gender_set.size))
)

df.withColumn("Gender", when($"Gender".isNull, randGenderUDF()).otherwise($"Gender")).groupBy($"Gender").count.show()
+------+-----+
|Gender|count|
+------+-----+
|Female|    5|
|  Male|    3|
+------+-----+    

【讨论】:

以上是关于从集合中随机替换 spark 数据集列值的主要内容,如果未能解决你的问题,请参考以下文章

将值替换为数据集列上的整数

Spark SQL - 转换为数据集列的 UUID 引发解析异常

数据集列中的字符串替换不起作用

如何在火花中遍历数据集列?

根据最大 Spark Scala 替换列值

如何通过 Python 中的 Plotly 从 Dash 的下拉列表中选择数据集列?