scala - 有条件地转换火花中的列
问题描述
假设我有一个如下数据框:
import org.apache.spark.sql.{Row, DataFrame, SparkSession}
import org.apache.spark.sql.types.{StructType, StructField, IntegerType, StringType, DoubleType, NumericType}
import org.apache.spark.sql.functions.{udf, col, skewness}
val someData = Seq(
Row(8, "bat"),
Row(64, "mouse"),
Row(-27, "horse"),
Row(null, "mouse"),
Row(27, null)
)
val someSchema = List(
StructField("number", IntegerType, true),
StructField("word", StringType, true)
)
val someDF = spark.createDataFrame(
spark.sparkContext.parallelize(someData),
StructType(someSchema)
)
val df = someDF.withColumn("constantColumn", lit(1))
我想计算具有 NumericType-like 类型的每一列的偏度。然后,如果列的偏度高于某个阈值,我想通过f(x) = log(x + 1)
. (我知道对负数据执行对数转换会给出 NaN,但我想最终编写代码来考虑这种可能性)。
到目前为止我已经尝试过:
我找到了一种方法,但它需要一个可变的 dataframe df
。根据我有限的理解,这是不可取的。
val log1p = scala.math.log1p(_)
val log1pUDF = udf(scala.math.log1p(_: Double))
val transformThreshold = 0.04
// filter those columns which have a type that inherits from NumericType
val numericColumns = df.columns.filter(column => df.select(column).schema(0).dataType.isInstanceOf[NumericType])
// for columns having NumericType, filter those that are sufficiently skewed
val columnsToTransform = numericColumns.filter(numericColumn => df.select(skewness(df(numericColumn))).head.getDouble(0) > transformThreshold)
// for all columns that are sufficiently skewed, perform log1p transform and add it to df
for(column <- columnsToTransform) {
// df should be mutable here!
df = df.withColumn(column + "_log1p", log1pUDF(df(column)))
}
我的问题:
- 如何在不使用可变数据框的情况下实现目标?
- 有没有更简单/更快的方法来实现我试图做的事情?
(在 Spark 2.4.0、Scala 2.11.12 上运行。)
解决方案
您可以使用递归函数来代替for()
结构:
def rec(df: DataFrame, columns: List[String]): DataFrame = columns match {
case Nil => df
case h :: xs => rec(df.withColumn(s"${h}_log1p", log1pUDF(col(h))), xs)
}
推荐阅读
- css - CSS卡在悬停时呈锯齿状,文本也在框外流动(溢出)
- azure - 如何在没有安全性的情况下在 azure 上设置 web api?
- azure-devops - Azure DevOps Pipeline 在部署中定义变量并在后续作业中重用
- blockchain - 松露中artifacts和artifacts.new之间的区别
- google-cloud-platform - Logsink 到 bigquery 分区不起作用
- virtual-memory - 限制进程的虚拟地址范围?
- php - 如何使用 PHPDoc?
- sql - 是否有一种将可空列级联到引用表的非触发方式?
- javascript - 无法解决承诺拒绝并发送数组作为响应
- forms - 如何在 ms 访问中更新单个表单上的多个表?