J'ai un DataFrame qui ressemble à quelque chose comme ça. Je souhaite opérer le jour du date_time
champ.
root
|-- Host: string (nullable = true)
|-- user_id: string (nullable = true)
|-- date_time: timestamp (nullable = true)
J'ai essayé d'ajouter une colonne pour extraire la journée. Jusqu'à présent, mes tentatives ont échoué.
df = df.withColumn("day", df.date_time.getField("day"))
org.Apache.spark.sql.AnalysisException: GetField is not valid on fields of type TimestampType;
Cela a également échoué
df = df.withColumn("day", df.select("date_time").map(lambda row: row.date_time.day))
AttributeError: 'PipelinedRDD' object has no attribute 'alias'
Une idée de comment cela peut être fait?
Vous pouvez utiliser un simple map
:
df.rdd.map(lambda row:
Row(row.__fields__ + ["day"])(row + (row.date_time.day, ))
)
Une autre option consiste à enregistrer une fonction et à exécuter une requête SQL:
sqlContext.registerFunction("day", lambda x: x.day)
sqlContext.registerDataFrameAsTable(df, "df")
sqlContext.sql("SELECT *, day(date_time) as day FROM df")
Enfin, vous pouvez définir udf comme ceci:
from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType
day = udf(lambda date_time: date_time.day, IntegerType())
df.withColumn("day", day(df.date_time))
[~ # ~] éditez [~ # ~] :
En fait, si vous utilisez la fonction brute SQL day
est déjà définie (au moins dans Spark 1.4), vous pouvez donc omettre l'enregistrement udf. Il fournit également un certain nombre de fonctions de traitement de date différentes, y compris :
des getters comme year
, month
, dayofmonth
from_unixtime
et des formateurs comme date_format
Il est également possible d'utiliser des expressions de date simples comme:
current_timestamp() - expr("INTERVAL 1 HOUR")
Cela signifie que vous pouvez créer des requêtes relativement complexes sans passer de données à Python. Par exemple:
df = sc.parallelize([
(1, "2016-01-06 00:04:21"),
(2, "2016-05-01 12:20:00"),
(3, "2016-08-06 00:04:21")
]).toDF(["id", "ts_"])
now = lit("2016-06-01 00:00:00").cast("timestamp")
five_months_ago = now - expr("INTERVAL 5 MONTHS")
(df
# Cast string to timestamp
# For Spark 1.5 use cast("double").cast("timestamp")
.withColumn("ts", unix_timestamp("ts_").cast("timestamp"))
# Find all events in the last five months
.where(col("ts").between(five_months_ago, now))
# Find first Sunday after the event
.withColumn("next_sunday", next_day(col("ts"), "Sun"))
# Compute difference in days
.withColumn("diff", datediff(col("ts"), col("next_sunday"))))