web-dev-qa-db-fra.com

Comment obtenir la semaine du jour du mois en utilisant pyspark

J'ai un dataframe log_df: enter image description here

Je génère une nouvelle trame de données basée sur le code suivant:

from pyspark.sql.functions import split, regexp_extract 
split_log_df = log_df.select(regexp_extract('value', r'^([^\s]+\s)', 1).alias('Host'),
                          regexp_extract('value', r'^.*\[(\d\d/\w{3}/\d{4}:\d{2}:\d{2}:\d{2} -\d{4})]', 1).alias('timestamp'),
                          regexp_extract('value', r'^.*"\w+\s+([^\s]+)\s+HTTP.*"', 1).alias('path'),
                          regexp_extract('value', r'^.*"\s+([^\s]+)', 1).cast('integer').alias('status'),
                          regexp_extract('value', r'^.*\s+(\d+)$', 1).cast('integer').alias('content_size'))
split_log_df.show(10, truncate=False)

le nouveau dataframe est comme: enter image description here

J'ai besoin d'une autre colonne montrant la journée de la semaine, quelle serait la meilleure façon élégante de la créer? idéalement, il suffit d'ajouter un champ de type udf dans la sélection.

Merci beaucoup.

Mise à jour: ma question est différente de celle du commentaire, ce dont j'ai besoin est de faire le calcul en fonction d'une chaîne dans log_df, pas en fonction de l'horodatage comme le commentaire, donc ce n'est pas une question en double. Merci.

7
mdivk

J'ai finalement résolu la question moi-même, voici la solution complète:

  1. importer date_format, datetime, DataType
  2. tout d'abord, modifiez l'expression rationnelle pour extraire 01/Jul/1995
  3. convertir 01/Jul/1995 en DateType en utilisant func
  4. créer un udf dayOfWeek pour obtenir le jour de la semaine dans un format bref (lun, mar, ...)
  5. en utilisant le udf pour convertir le DateType 01/Jul/1995 en jour de semaine qui est Sat enter image description here

Je ne suis pas satisfait de ma solution car elle semble tellement en zig-zag, il serait apprécié que quelqu'un puisse trouver une solution plus élégante, merci d'avance.

0
mdivk

Je suggère une méthode un peu différente

from pyspark.sql.functions import date_format
df.select('capturetime', date_format('capturetime', 'u').alias('dow_number'), date_format('capturetime', 'E').alias('dow_string'))
df3.show()

Il donne ...

+--------------------+----------+----------+
|         capturetime|dow_number|dow_string|
+--------------------+----------+----------+
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
|2017-06-05 10:05:...|         1|       Mon|
22
Karel Marik

J'ai fait cela pour obtenir les jours de semaine à partir de la date:

def get_weekday(date):
    import datetime
    import calendar
    month, day, year = (int(x) for x in date.split('/'))    
    weekday = datetime.date(year, month, day)
    return calendar.day_name[weekday.weekday()]

spark.udf.register('get_weekday', get_weekday)

Exemple d'utilisation:

df.createOrReplaceTempView("weekdays")
df = spark.sql("select DateTime, PlayersCount, get_weekday(Date) as Weekday from weekdays")

enter image description here

2
Sulekha Aloorravi

Puisque SPARK 1.5.0 a une fonction date_format qui accepte un format comme argument. Ce format renvoie le nom d'un jour de la semaine à partir d'un horodatage:

select date_format(my_timestamp, 'EEEE') from ....

Résultat: ex. 'Mardi'

Comment obtenir le jour de la semaine dans SparkSQL?

1
abdelhadi danba

cela a fonctionné pour moi:

recréer des données similaires à votre exemple:

df = spark.createDataFrame(\
    [(1, "2017-11-01 22:05:01 -0400")\
     ,(2, "2017-11-02 03:15:16 -0500")\
     ,(3, "2017-11-03 19:32:24 -0600")\
      ,(4, "2017-11-04 07:47:44 -0700")\
    ], ("id", "date"))

df.toPandas()
    id  date
0   1   2017-11-01 22:05:01 -0400
1   2   2017-11-02 03:15:16 -0500
2   3   2017-11-03 19:32:24 -0600
3   4   2017-11-04 07:47:44 -0700

créer une fonction lambda pour gérer la conversion en semaine

funcWeekDay =  udf(lambda x: datetime.strptime(x, '%Y-%m-%d').strftime('%w'))
  • extraire la date dans la colonne shortdate
  • créer une colonne avec weeday, en utilisant la fonction lambda
  • supprimez la colonne shortdate

le code:

from pyspark.sql.functions import udf,col
    from datetime import datetime


df=df.withColumn('shortdate',col('date').substr(1, 10))\
     .withColumn('weekDay', funcWeekDay(col('shortdate')))\
     .drop('shortdate')

résultat:

df.toPandas()
    id  date                     weekDay
0   1   2017-11-01 22:05:01 -0400   3
1   2   2017-11-02 03:15:16 -0500   4
2   3   2017-11-03 19:32:24 -0600   5
3   4   2017-11-04 07:47:44 -0700   6
0
Grant Shannon