2
votes

Convertir la chaîne de date en horodatage pour le tri avec une précision inférieure à la seconde

J'ai une colonne date dans un dataframe pySpark avec des dates au format suivant:

df_new = df.withColumn(
    'date1',
    F.to_timestamp("date", "yyyy-dd-MM'T'hh:mm:ss.s")
)

Je veux convertir les dates de cette colonne de chaîne en horodatage (ou quelque chose que je peux trier en fonction de la date). Jusqu'à présent, j'ai essayé ce qui suit:

new_df = df.withColumn(
    'date',
    from_unixtime(
        unix_timestamp(col(('date')), "yyyy-MM-dd'T'hh:mm:ss.SSS"), 
        "yyyy-MM-dd'T'HH:mm:ss.SSS"
    )
)

et ceci

new_df = df.withColumn(
    'date', 
    unix_timestamp("date", "YYYY-MM-DD'T'hh:mm:ss.s").cast("double").cast("timestamp")
)

et ceci

2018-02-01T13:13:12.023507

J'ai essayé tout ce que j'ai trouvé dans d'autres questions similaires mais jusqu'à présent, rien ne fonctionne. J'ai également essayé un format différent aaaa-MM-jj'T'HH: mm: ss.ssssss sans succès. Que me manque-t-il?


0 commentaires

3 Réponses :


2
votes

Supposons que vous disposiez du DataFrame suivant:

from pyspark.sql.functions import split

df.withColumn(
    'order_column',
    unix_timestamp('date', "yyyy-MM-dd'T'hh:mm:ss") + split('date', "\.")[1]/1000000.0
).sort("order_column").show(truncate=False)
#+--------------------------+-------------------+
#|date                      |order_column       |
#+--------------------------+-------------------+
#|2018-02-01T13:13:12.023507|1.517508792023507E9|
#|2018-02-01T13:13:12.323507|1.517508792323507E9|
#+--------------------------+-------------------+

unixtimestamp uniquement prend en charge la seconde précision . Si vous ne vous souciez que du tri basé sur la date, vous pouvez faire ce qui suit:

from pyspark.sql.functions import col, unix_timestamp
df.withColumn(
    'new_date',
    unix_timestamp(col('date'), "yyyy-MM-dd'T'hh:mm:ss").cast("timestamp")
).sort('new_date').show(truncate=False)
#+--------------------------+---------------------+
#|date                      |new_date             |
#+--------------------------+---------------------+
#|2018-02-01T13:13:12.323507|2018-02-01 13:13:12.0|
#|2018-02-01T13:13:12.023507|2018-02-01 13:13:12.0|
#+--------------------------+---------------------+

Mais comme ces deux exemples de lignes ont la même date et heure jusqu'à la seconde , le tri ici sera indéterminé.

Si la sous-seconde partie est importante pour vous, vous pouvez écrire votre propre fonction pour gérer cela. Une façon est de diviser la colonne date sur le . et de diviser par 1000000.0 pour obtenir les microsecondes. Ajoutez ensuite ceci à unixtimestamp pour le tri:

df = spark.createDataFrame(
    [('2018-02-01T13:13:12.023507', ), ('2018-02-01T13:13:12.323507', )], 
    ["date"]
)
df.show(truncate=False)
#+--------------------------+
#|date                      |
#+--------------------------+
#|2018-02-01T13:13:12.023507|
#|2018-02-01T13:13:12.323507|
#+--------------------------+


1 commentaires

Je pense que cela devrait être de pyspark.sql.functions import col, unix_timestamp



0
votes

Vous pouvez essayer udf comme ci-dessous.

    format = '%Y-%m-%d %H:%M:%S:%s'
    func = udf (lambda x: datetime.strptime(x, format), TimestampType())


0 commentaires

1
votes

pour Spark> = 2.2 une approche alternative à unix_timestamp () consiste à utiliser to_timestamp():

from pyspark.sql.functions import col, to_timestamp

new_df = df.withColumn('converted_date',to_timestamp(col('date'), "yyyy-MM-dd'T'HH:mm:ss"))


0 commentaires