Файловый фрейм PySpark преобразует необычный строковый формат в Timestamp

Я использую PySpark через Spark 1.5.0. У меня необычный формат String в строках столбца для значений даты и времени. Это выглядит так:

Row[(daytetime='2016_08_21 11_31_08')]

Есть ли способ преобразовать этот неортодоксальный yyyy_mm_dd hh_mm_dd времени? Что-то, что может в конечном итоге прийти по линии

df = df.withColumn("date_time",df.daytetime.astype('Timestamp'))

Я думал, что функции Spark SQL, такие как regexp_replace могут работать, но, конечно, мне нужно заменить _ на - в половине даты и _ на : в части времени.

Я думал, что смогу разбить столбец на 2, используя substring и посчитать в обратном направлении с конца времени. Затем выполните 'regexp_replace' отдельно, затем объедините. Но это кажется многим операциям? Есть ли более простой способ?

Ответ 1

Spark> = 2,2

from pyspark.sql.functions import to_timestamp

(sc
    .parallelize([Row(dt='2016_08_21 11_31_08')])
    .toDF()
    .withColumn("parsed", to_timestamp("dt", "yyyy_MM_dd HH_mm_ss"))
    .show(1, False))

## +-------------------+-------------------+
## |dt                 |parsed             |
## +-------------------+-------------------+
## |2016_08_21 11_31_08|2016-08-21 11:31:08|
## +-------------------+-------------------+

Spark & lt; 2.2

Это ничто, с чем unix_timestamp не может справиться:

from pyspark.sql import Row
from pyspark.sql.functions import unix_timestamp

(sc
    .parallelize([Row(dt='2016_08_21 11_31_08')])
    .toDF()
    .withColumn("parsed", unix_timestamp("dt", "yyyy_MM_dd HH_mm_ss")
    # For Spark <= 1.5
    # See issues.apache.org/jira/browse/SPARK-11724 
    .cast("double")
    .cast("timestamp"))
    .show(1, False))

## +-------------------+---------------------+
## |dt                 |parsed               |
## +-------------------+---------------------+
## |2016_08_21 11_31_08|2016-08-21 11:31:08.0|
## +-------------------+---------------------+

В обоих случаях строка формата должна быть совместима с Java SimpleDateFormat.

Ответ 2

Ответ на нуль323 отвечает на вопрос, но я хотел бы добавить, что если ваша строка datetime имеет стандартный формат, вы должны иметь возможность использовать ее непосредственно в типе timestamp:

df.withColumn('datetime', col('datetime_str').cast('timestamp'))

Это имеет преимущество обработки миллисекунд, в то время как unix_timestamp имеет только вторую точность (to_timestamp работает с миллисекундами, но требует Spark> = 2.2, как указано в ноль323). Я тестировал его на Spark 2.3.0, используя следующий формат: '2016-07-13 14: 33: 53.979' (с миллисекундами, но он также работает без них).

Ответ 3

Я полностью согласен с выбранным ответом, однако я хотел бы установить формат 'yyyy_MM_dd HH_mm_ss', чтобы избежать проблем с метками времени, такими как '2019_01_27 16_00_00' → Note note> 12