El siguiente marco de datos de chispa tiene start_t y end_t en formato Unix pero tiene una e exponencial.

+------+----------------+------------------+--------+----------+----------+-------+-----------+-----------+-----------+-------------+-------+---------------+----------------+
| alt_t|           end_t|engine_fuel_rate_t|   lat_t|left_max_t|left_min_t|  lon_t|plm3_incl_t|right_max_t|right_min_t|road_class_u8|speed_t|sprung_weight_t|         start_t|
+------+----------------+------------------+--------+----------+----------+-------+-----------+-----------+-----------+-------------+-------+---------------+----------------+
|1237.5|1.521956985733E9|                 0|-27.7314|       0.0|       0.0|22.9552|        1.5|        0.0|        0.0|            0|   17.4|          198.0| 1.52195698056E9|
|1236.5|1.521956989922E9|                 0|-27.7316|       0.0|       0.0|22.9552|       -3.3|        0.0|        0.0|            0|   17.6|          156.1|1.521956985733E9|
|1234.5|1.521956995378E9|                 0|-27.7318|       0.0|       0.0|22.9552|       -2.7|        0.0|        0.0|            0|   11.9|          148.6|1.521956989922E9|
|1230.5|1.521957001498E9|                 0| -27.732|       0.0|       0.0|22.9551|        2.3|        0.0|        0.0|            0|   13.2|          169.1|1.521956995378E9|

Como es doble, no se puede convertir directamente en marca de tiempo. Pasará por un error que indica que debe ser una cadena.

+------+----------------+------------------+--------+----------+----------+-------+-----------+-----------+-----------+-------------+-------+---------------+-------+
| alt_t|           end_t|engine_fuel_rate_t|   lat_t|left_max_t|left_min_t|  lon_t|plm3_incl_t|right_max_t|right_min_t|road_class_u8|speed_t|sprung_weight_t|start_t|
+------+----------------+------------------+--------+----------+----------+-------+-----------+-----------+-----------+-------------+-------+---------------+-------+
|1237.5|1.521956985733E9|                 0|-27.7314|       0.0|       0.0|22.9552|        1.5|        0.0|        0.0|            0|   17.4|          198.0|   null|
|1236.5|1.521956989922E9|                 0|-27.7316|       0.0|       0.0|22.9552|       -3.3|        0.0|        0.0|            0|   17.6|          156.1|   null|
|1234.5|1.521956995378E9|                 0|-27.7318|       0.0|       0.0|22.9552|       -2.7|        0.0|        0.0|            0|   11.9|          148.6|   null|

Por lo tanto, utilicé el siguiente código:

%scala

val df2 = df.withColumn("start_t", df("start_t").cast("string"))
val df3 = df2.withColumn("end_t", df("end_t").cast("string"))
val filteredDF = df3.withColumn("start_t", unix_timestamp($"start_t", "yyyyMMddHHmmss").cast("timestamp"))
filteredDF.show()

Obtengo nulo en start_t y creo que se debe a la E (signo exponencial). Lo he probado en pandas python, las fechas son válidas y generan resultados. Sé que hay una forma de utilizar la precisión para cambiar esto. Estoy tratando de convertirlo en una marca de tiempo en el formato aaaa-MM-dd HH: mm: ss y tener una columna separada solo para la hora y la fecha.

Nota: se hizo una pregunta similar pero no se respondió. Scala Spark: convierte una columna doble en una columna de fecha y hora en el marco de datos

1
Sade 17 oct. 2018 a las 09:15

2 respuestas

La mejor respuesta

Encadena el casting desde String -> Double -> Timestamp. Lo siguiente funciona

scala> val df = Seq(("1237.5","1.521956985733E9"),("1236.5","1.521956989922E9"),("1234.5","1.521956995378E9"),("1230.5","1.521957001498E9")).toDF("alt_t","end_t")
df: org.apache.spark.sql.DataFrame = [alt_t: string, end_t: string]

scala> df.withColumn("end_t",'end_t.cast("double").cast("timestamp")).show(false)
+------+-----------------------+
|alt_t |end_t                  |
+------+-----------------------+
|1237.5|2018-03-25 01:49:45.733|
|1236.5|2018-03-25 01:49:49.922|
|1234.5|2018-03-25 01:49:55.378|
|1230.5|2018-03-25 01:50:01.498|
+------+-----------------------+


scala>

ACTUALIZACIÓN1

scala> val df = Seq(("1237.5","1.521956985733E9"),("1236.5","1.521956989922E9"),("1234.5","1.521956995378E9"),("1230.5","1.521957001498E9")).toDF("alt_t","end_t").withColumn("end_t",'end_t.cast("double").cast("timestamp"))
df: org.apache.spark.sql.DataFrame = [alt_t: string, end_t: timestamp]

scala> df.printSchema
root
 |-- alt_t: string (nullable = true)
 |-- end_t: timestamp (nullable = true)


scala>
0
stack0114106 17 oct. 2018 a las 09:44

Debería poder lanzar un doble a la marca de tiempo como se muestra a continuación

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

scala>
     | val df = Seq((1237.5,1.521956985733E9),
     | (1236.5,1.521956989922E9),
     | (1234.5,1.521956995378E9),
     | (1230.5,1.521957001498E9)).toDF("alt_t","end_t")
df: org.apache.spark.sql.DataFrame = [alt_t: double, end_t: double]

scala>

scala> df.printSchema
root
 |-- alt_t: double (nullable = false)
 |-- end_t: double (nullable = false)


scala>

scala> df.withColumn("end_t",$"end_t".cast("timestamp")).show
+------+--------------------+
| alt_t|               end_t|
+------+--------------------+
|1237.5|2018-03-25 05:49:...|
|1236.5|2018-03-25 05:49:...|
|1234.5|2018-03-25 05:49:...|
|1230.5|2018-03-25 05:50:...|
+------+--------------------+
0
sramalingam24 17 oct. 2018 a las 06:47