[PYTHON] Vorsichtsmaßnahmen bei der Berechnung mit Zeichenfolge für TmeStampType von PySpark

Einführung

Es wird gesagt, dass es ein Muster gibt, das sich unbeabsichtigt verhält, wenn der Zeichenkettentyp des Datumsformats bei der Berechnung des TimeStampType von PySpark unachtsam verwendet wird.

Daher ist es möglich, mit einer Zeichenfolge für TimeStampType zu berechnen, es ist jedoch sicherer, datetime zu verwenden.

Beispiel

Ein spezielles Beispiel wird beschrieben.

Das hier gezeigte Beispiel stammt aus PySPark 2.4.4.

Überprüfungsdaten

Erstellen Sie mit dem folgenden Code einen Spark DataFrame mit Datumsdaten vom 1. Januar 2000 bis 5. Januar 2000 und führen Sie eine bedingte Verarbeitung für diese Datumsdaten durch.

Überprüfungsdaten


import pandas as pd
from pyspark.sql import functions as F

pdf = pd.DataFrame(pd.date_range(start='1/1/2000', periods=5), columns=['date'])
sdf = spark.createDataFrame(pdf, ['timestamp'])

Berechnung von TimeStampType und datetime

Die Operation mit datetime für TimeStampType funktioniert normal.

Berechnung von TimeStampType und datetime


target_datetime = datetime.strptime('2000-01-03', '%Y-%m-%d')

print('== datetime(2000-01-03)')
sdf.where(F.col('timestamp') == datetime.strptime('2000-01-03', '%Y-%m-%d')).show()
print('>  datetime(2000-01-03)')
sdf.where(F.col('timestamp') >  datetime.strptime('2000-01-03', '%Y-%m-%d')).show()
print('>= datetime(2000-01-03)')
sdf.where(F.col('timestamp') >= datetime.strptime('2000-01-03', '%Y-%m-%d')).show()
print('<  datetime(2000-01-03)')
sdf.where(F.col('timestamp') <  datetime.strptime('2000-01-03', '%Y-%m-%d')).show()
print('<= datetime(2000-01-03)')
sdf.where(F.col('timestamp') <= datetime.strptime('2000-01-03', '%Y-%m-%d')).show()
print('between datetime(2000-01-02) and datetime(2000-01-04)')
sdf.where(F.col('timestamp').between(datetime.strptime('2000-01-02', '%Y-%m-%d'), datetime.strptime('2000-01-04', '%Y-%m-%d'))).show()

Ausgabeergebnis


== datetime(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
+-------------------+

>  datetime(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

>= datetime(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

<  datetime(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
+-------------------+

<= datetime(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
|2000-01-03 00:00:00|
+-------------------+

between datetime(2000-01-02) and datetime(2000-01-04)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-02 00:00:00|
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
+-------------------+

Berechnung von TimeStampType und String (Datum / Uhrzeit-Format)

Als nächstes wird das Ergebnis angezeigt, wenn die Zeichenfolge im Datum / Uhrzeit-Format (JJJJ-MM-TT HH: MM: SS) angegeben wird. Die Zeichenfolge scheint implizit gegossen zu sein, und Operationen können problemlos ausgeführt werden.

TimeStampType und Zeichenfolge(Datum / Uhrzeit-Format)Berechnung


print('== string(2000-01-03 00:00:00)')
sdf.where(F.col('timestamp') == '2000-01-03 00:00:00').show()
print('>  string(2000-01-03 00:00:00)')
sdf.where(F.col('timestamp') >  '2000-01-03 00:00:00').show()
print('>= string(2000-01-03 00:00:00)')
sdf.where(F.col('timestamp') >= '2000-01-03 00:00:00').show()
print('<  string(2000-01-03 00:00:00)')
sdf.where(F.col('timestamp') <  '2000-01-03 00:00:00').show()
print('<= string(2000-01-03 00:00:00)')
sdf.where(F.col('timestamp') <= '2000-01-03 00:00:00').show()
print('between string(2000-01-02 00:00:00) and string(2000-01-04 00:00:00)')
sdf.where(F.col('timestamp').between('2000-01-02 00:00:00', '2000-01-04 00:00:00')).show()

Ausgabeergebnis


== string(2000-01-03 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
+-------------------+

>  string(2000-01-03 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

>= string(2000-01-03 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

<  string(2000-01-03 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
+-------------------+

<= string(2000-01-03 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
|2000-01-03 00:00:00|
+-------------------+

between string(2000-01-02 00:00:00) and string(2000-01-04 00:00:00)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-02 00:00:00|
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
+-------------------+

Berechnung von TimeStampType und String (Datumsformat)

Schließlich wird das Ergebnis angezeigt, wenn die Zeichenfolge im Datumsformat (JJJJ-MM-TT) angegeben wird. In diesem Fall gibt es ein Muster, das zu einem Verhalten führt, das nicht intuitiv beabsichtigt ist.

TimeStampType und Zeichenfolge(Datumsformat)Berechnung


print('== string(2000-01-03)')
sdf.where(F.col('timestamp') == '2000-01-03').show()
print('>  string(2000-01-03)')  #Unbeabsichtigtes Muster
sdf.where(F.col('timestamp') >  '2000-01-03').show()
print('>= string(2000-01-03)')
sdf.where(F.col('timestamp') >= '2000-01-03').show()
print('<  string(2000-01-03)')
sdf.where(F.col('timestamp') <  '2000-01-03').show()
print('<= string(2000-01-03)')  #Unbeabsichtigtes Muster
sdf.where(F.col('timestamp') <= '2000-01-03').show()
print('between string(2000-01-02) and string(2000-01-04)')  #Unbeabsichtigtes Muster
sdf.where(F.col('timestamp').between('2000-01-02', '2000-01-04')).show()

Ausgabeergebnis


== string(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
+-------------------+

>  string(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

>= string(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-03 00:00:00|
|2000-01-04 00:00:00|
|2000-01-05 00:00:00|
+-------------------+

<  string(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
+-------------------+

<= string(2000-01-03)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-01 00:00:00|
|2000-01-02 00:00:00|
+-------------------+

between string(2000-01-02) and string(2000-01-04)
+-------------------+
|          timestamp|
+-------------------+
|2000-01-02 00:00:00|
|2000-01-03 00:00:00|
+-------------------+

Über das Verhalten

Aufgrund der impliziten Umwandlung von Zeichenfolgen in TimeStamp zum Zeitpunkt des Betriebs sind "TimeStamp (2000-01-01 00:00:00)" und "TimeStamp (Zeichenfolge (2000-01-01 00:00:00))" gleichwertig. Das Ergebnis ist wie "TimeStamp (2000-01-01 00:00:00) <TimeStamp (Zeichenfolge (2000-01-01))".

Daraus kann man sich vorstellen, dass die Werte für Stunden ("00: 00: 00" im obigen Beispiel) nicht richtig verarbeitet werden. (Für strenge Spezifikationen müssen Sie die Scala-Quelle auf Details des Vorgangs überprüfen.)

(Extra Edition) Vom String-Typ zum Zeitstempel-Typ

Übrigens scheint es beim Casting von StringType nach TimeStampType richtig zu sein. Ein Beispiel wird hier nicht gezeigt, aber wie beim obigen Muster funktioniert es normal, auch wenn die arithmetische Verarbeitung mit TimeStampType ausgeführt wird (natürlich, weil es zwischen TimeStampType-Typen liegt).

Umwandlung von StringType in TimeStampType


df = spark.createDataFrame([('2000',), ('2000-01-01',), ('2000-01-01 00:00:00',) ], ['str'])
df = df.withColumn('timestamp', F.col('str').cast('timestamp'))
df.show()

Ausgabeergebnis


+-------------------+-------------------+
|                str|          timestamp|
+-------------------+-------------------+
|               2000|2000-01-01 00:00:00|
|         2000-01-01|2000-01-01 00:00:00|
|2000-01-01 00:00:00|2000-01-01 00:00:00|
+-------------------+-------------------+

Recommended Posts

Vorsichtsmaßnahmen bei der Berechnung mit Zeichenfolge für TmeStampType von PySpark
Zusammenfassung der Tools zum Betreiben der Windows-Benutzeroberfläche mit Python
Vorsichtsmaßnahmen bei der Installation von Tensorflow mit Anaconda
Achten Sie beim Drucken von Japanisch mit Python 3 auf LANG für UnicodeEncodeError
Informationen zu Transaktionen beim Betrieb von PostgreSQL mit Psycopg2
Messen Sie die Ähnlichkeit von Inhalten mit Pyspark
4. Nacht der Schleife mit für
Vorsichtsmaßnahmen bei Verwendung von sechs mit Python 2.5
Zu beachtende Punkte bei der Lösung von DP-Problemen mit Python
Vorsichtsmaßnahmen bei Verwendung der for-Anweisung in Pandas
Snippet-Zusammenfassung bei der Entwicklung mit Go
Die dritte Nacht der Runde mit für
Memorandum für die Migration mit GORM
Die zweite Nacht der Runde mit für
Ein Memorandum of Method, das häufig bei der Analyse von Daten mit Pandas verwendet wird (für Anfänger)
Vorsichtsmaßnahmen beim Umgang mit Kontrollstrukturen in Python 2.6
Vorsichtsmaßnahmen bei der Verwendung von tf.keras.layers.TimeDistributed für die benutzerdefinierte Ebene von tf.keras
Vorsichtsmaßnahmen bei Verwendung der Google Cloud-Bibliothek mit GAE / py
[Webentwicklung mit Python] Vorsichtsmaßnahmen beim Speichern von Cookies