创建一个新的数据框架,并将字段值设置为空/空值。

45
我正在从现有的数据框创建一个新的数据框,但需要在这个新的数据框中添加新的列(下面的代码中是"field1")。我该如何做?如果可以提供可行的样例代码,将不胜感激。
val edwDf = omniDataFrame 
  .withColumn("field1", callUDF((value: String) => None)) 
  .withColumn("field2",
    callUdf("devicetypeUDF", (omniDataFrame.col("some_field_in_old_df")))) 

edwDf
  .select("field1", "field2")
  .save("odsoutdatafldr", "com.databricks.spark.csv"); 
2个回答

109

可以使用lit(null)

import org.apache.spark.sql.functions.{lit, udf}

case class Record(foo: Int, bar: String)
val df = Seq(Record(1, "foo"), Record(2, "bar")).toDF

val dfWithFoobar = df.withColumn("foobar", lit(null: String))

这里的一个问题是列类型为 null

scala> dfWithFoobar.printSchema
root
 |-- foo: integer (nullable = false)
 |-- bar: string (nullable = true)
 |-- foobar: null (nullable = true)

如果不进行特殊处理,csv写入器不会保留这种数据类型。如果有强制要求,您可以将该列转换为特定类型(比如字符串),使用DataType

import org.apache.spark.sql.types.StringType

df.withColumn("foobar", lit(null).cast(StringType))

或字符串描述

df.withColumn("foobar", lit(null).cast("string"))

或者使用这样的UDF:

val getNull = udf(() => None: Option[String]) // Or some other type

df.withColumn("foobar", getNull()).printSchema
root
 |-- foo: integer (nullable = false)
 |-- bar: string (nullable = true)
 |-- foobar: string (nullable = true)

这里可以找到Python的等效方法: 在Spark DataFrame中添加一个空列


2
@zero323,感谢分享,非常有帮助。请查看我的编辑以支持其他类型。 - Dmitriy Selivanov
@DmitriySelivanov 谢谢您的帮助编辑。我在一段时间前尝试使用字面量后放弃了使用 Option 的想法 :) - zero323
有没有可能输出一个空的结构体,以便将其保存到具有空值但结构类型的 Parquet 中?在 2.4 版本中,val getNull = udf(() => None: Option[StructType]) 对我无效。 - jmng

20

只是扩展了@zero323提供的完美答案,这里提供了一个可以从Spark 2.2.0开始使用的解决方案。

import org.apache.spark.sql.functions.typedLit

df.withColumn("foobar", typedLit[Option[String]](None)).printSchema
root
 |-- foo: integer (nullable = false)
 |-- bar: string (nullable = true)
 |-- foobar: string (nullable = true)

这类似于第三种解决方案,但不使用任何用户定义函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接