Spark Scala使用今天的时间戳填充NA

时间:2016-12-19 14:35:33

标签: apache-spark apache-spark-sql

如何替换timestamp类型列中的所有空值?

我希望这更容易,但我似乎无法正确获取类型。 我假设一个解决方案是将列转换为String,在字符串中填写今天的日期,然后重新转换为时间戳,但是,是否有更优雅的解决方案?

val today = java.time.LocalDate.now()
var todayStamp = java.sql.Timestamp.valueOf(today.atStartOfDay());
df = df.na.fill(Map("expiration" -> todayStamp))

结果

java.lang.IllegalArgumentException: Unsupported value type java.sql.Timestamp

今天使用并没有使用unix_timestamp(string).cast("timestamp") 期望列而不是字符串。我想我可以在" ugly"我上面提到的方法。

稍后编辑: 忘记提及,在时间戳列上使用Int或String和df.na.fill方法也会导致错误:

org.apache.spark.sql.AnalysisException: cannot resolve 'coalesce(expiration, 0)' due to data type mismatch: input to function coalesce should all be the same type, but it's [timestamp, int];

4 个答案:

答案 0 :(得分:4)

您还可以使用coalesce

import org.apache.spark.sql.functions._
df.withColumn("expiration", coalesce(col("expiration"), current_timestamp()))

这是一个可重复的例子:

import org.apache.spark.sql.functions._

val df = Seq(
  Tuple1(None: Option[Timestamp]),
  Tuple1(Some(Timestamp.valueOf("2010-01-01 00:00:00")))
).toDF("expiration")

df.withColumn("expiration", coalesce(col("expiration"), current_timestamp())).show()

答案 1 :(得分:2)

根据文件:

值必须是以下类型:整数,长整数,浮点数,双精度,字符串,布尔值替换值会转换为列数据类型。

使用na.fill - 您需要提供整数,Long或String的日期,如果列的类型为“timestamp”,它可能会自动转换为“timestamp”

https://spark.apache.org/docs/latest/api/java/org/apache/spark/sql/DataFrameNaFunctions.html

<强>填

public Dataset<Row> fill(java.util.Map<String,Object> valueMap)

返回一个替换空值的新DataFrame。

地图的关键是列名,地图的值是替换值。 值必须是以下类型:Integer,Long,Float,Double,String,Boolean 替换值将转换为列数据类型

例如,以下内容将“A”列中的空值替换为字符串“unknown”,将“B”列中的空值替换为数值1.0。

import com.google.common.collect.ImmutableMap;
df.na.fill(ImmutableMap.of("A", "unknown", "B", 1.0));

答案 2 :(得分:0)

你可以简化:

import org.apache.spark.sql.functions._

df.withColumn("expiration", 
  when($"expiration".isNull, current_timestamp()).otherwise($"expiration"))

答案 3 :(得分:-1)

我可以在Java中做到这一点,首先将列值转换为String,然后使用df.na()将空字符串替换为默认值,然后将该列转换为时间戳。

输入数据

+-------------------+
|               date|
+-------------------+
|               null|
|2018-04-03 00:00:00|
+-------------------+

我的转变

df.withColumn(
    "stringDate", 
    col("date").cast(DataTypes.StringType))
        .na().fill("2018-04-01 00:00:00")
        .withColumn("finalDate", col("stringDate").cast(DataTypes.TimestampType))
        .select("finalDate");

最终输出

+-------------------+
|          finalDate|
+-------------------+
|2018-04-01 00:00:00|
|2018-04-03 00:00:00|
+-------------------+