web-dev-qa-db-fra.com

PySpark dataframe convertit un format de chaîne inhabituel en horodatage

J'utilise PySpark via Spark 1.5.0 . J'ai un format de chaîne inhabituel dans les lignes d'une colonne pour les valeurs datetime. Cela ressemble à ceci:

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

Existe-t-il un moyen de convertir ce format non-orthodoxe yyyy_mm_dd hh_mm_dd en un horodatage? Quelque chose qui pourrait éventuellement arriver le long de 

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

J'avais pensé que des fonctions Spark SQL telles que regexp_replace pourraient fonctionner, mais bien sûr, je dois remplacer _ par - dans le demi-date Et _ avec : dans la partie temporelle.

Je pensais pouvoir scinder la colonne en 2 en utilisant substring et compter à rebours dès la fin des temps. Ensuite, faites le 'regexp_replace' séparément, puis concaténez. Mais cela semble à beaucoup d'opérations? Y a-t-il un moyen plus facile?

14
PR102012

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 <2.2

Ce n'est rien que unix_timestamp ne puisse gérer:

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")
    .cast("double")
    .cast("timestamp"))
    .show(1, False))

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

Dans les deux cas, la chaîne de format doit être compatible avec Java SimpleDateFormat .

31
zero323

la réponse de zero323 répond à la question, mais je voulais ajouter que si votre chaîne de date/heure a un format standard, vous devriez pouvoir la convertir directement en type d'horodatage:

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

Il a l'avantage de gérer millisecondes , alors que unix_timestamp n'a qu'une seconde précision (to_timestamp fonctionne également en millisecondes mais requiert Spark> = 2.2 comme indiqué par zéro323). Je l'ai testé sur Spark 2.3.0, en utilisant le format suivant: '2016-07-13 14: 33: 53.979' (en millisecondes, mais cela fonctionne aussi sans eux).

1
Florent F

Je suis tout à fait d’accord avec la réponse choisie, mais j’aimerais définir le format sur 'yyyy_MM_dd HH_mm_ss' pour éviter les problèmes d’horodatage tels que '2019_01_27 16_00_00' -> Note hour> 12

0
Pedro Muñoz