Chuyển đổi chuỗi pyspark sang định dạng ngày tháng


80

Tôi có khung dữ liệu pyspark ngày tháng với cột chuỗi ở định dạng MM-dd-yyyyvà tôi đang cố chuyển đổi khung này thành cột ngày tháng.

Tôi đã thử:

df.select(to_date(df.STRING_COLUMN).alias('new_date')).show()

và tôi nhận được một chuỗi null. Có ai giúp được không?


Trừ khi bạn đang sử dụng một trong các addon của TimeSeriesRDD (xem hội nghị Spark 2016 để thảo luận, có hai công cụ tôi biết nhưng cả hai vẫn đang được phát triển), không có nhiều công cụ tuyệt vời cho chuỗi thời gian. Do đó, tôi thấy hiếm khi có lý do để bận tâm chuyển đổi chuỗi thành các đối tượng datetime, nếu mục tiêu của bạn là các loại groupByhoạt động hoặc lấy mẫu lại nghiêm túc. Chỉ cần thực hiện chúng trên các cột chuỗi.
Jeff

Việc phân tích sẽ được thực hiện bằng cách sử dụng ít hoặc không, groupBynhưng khá dài và các nghiên cứu về hồ sơ bệnh án. Do đó, việc có thể điều chỉnh ngày là rất quan trọng
Jenks

Câu trả lời:


114

Cập nhật (1/10/2018):

Đối với Spark 2.2+, cách tốt nhất để làm điều này có lẽ là sử dụng hàm to_datehoặc to_timestamp, cả hai đều hỗ trợ formatđối số. Từ các tài liệu:

>>> from pyspark.sql.functions import to_timestamp
>>> df = spark.createDataFrame([('1997-02-28 10:30:00',)], ['t'])
>>> df.select(to_timestamp(df.t, 'yyyy-MM-dd HH:mm:ss').alias('dt')).collect()
[Row(dt=datetime.datetime(1997, 2, 28, 10, 30))]

Câu trả lời gốc (dành cho Spark <2.2)

Có thể (thích hơn?) Để làm điều này mà không có udf:

from pyspark.sql.functions import unix_timestamp, from_unixtime

df = spark.createDataFrame(
    [("11/25/1991",), ("11/24/1991",), ("11/30/1991",)], 
    ['date_str']
)

df2 = df.select(
    'date_str', 
    from_unixtime(unix_timestamp('date_str', 'MM/dd/yyy')).alias('date')
)

print(df2)
#DataFrame[date_str: string, date: timestamp]

df2.show(truncate=False)
#+----------+-------------------+
#|date_str  |date               |
#+----------+-------------------+
#|11/25/1991|1991-11-25 00:00:00|
#|11/24/1991|1991-11-24 00:00:00|
#|11/30/1991|1991-11-30 00:00:00|
#+----------+-------------------+

3
Đây là câu trả lời chính xác. Sử dụng udf cho điều này sẽ phá hủy hiệu suất của bạn.
gberger

8
từ pyspark.sql.functions nhập từ_unixtime, unix_timestamp
Quetzalcoatl

Lưu ý rằng bạn có thể tìm thấy tham chiếu định dạng ngày java tại đây: docs.oracle.com/javase/6/docs/api/java/text/…
RobinL

3
Cũng lưu ý rằng to_date()với đối số định dạng là spark 2.2+. to_datetồn tại trước 2.2, nhưng tùy chọn định dạng không tồn tại
RobinL

41
from datetime import datetime
from pyspark.sql.functions import col, udf
from pyspark.sql.types import DateType



# Creation of a dummy dataframe:
df1 = sqlContext.createDataFrame([("11/25/1991","11/24/1991","11/30/1991"), 
                            ("11/25/1391","11/24/1992","11/30/1992")], schema=['first', 'second', 'third'])

# Setting an user define function:
# This function converts the string cell into a date:
func =  udf (lambda x: datetime.strptime(x, '%m/%d/%Y'), DateType())

df = df1.withColumn('test', func(col('first')))

df.show()

df.printSchema()

Đây là đầu ra:

+----------+----------+----------+----------+
|     first|    second|     third|      test|
+----------+----------+----------+----------+
|11/25/1991|11/24/1991|11/30/1991|1991-01-25|
|11/25/1391|11/24/1992|11/30/1992|1391-01-17|
+----------+----------+----------+----------+

root
 |-- first: string (nullable = true)
 |-- second: string (nullable = true)
 |-- third: string (nullable = true)
 |-- test: date (nullable = true)

6
udfKhông cần thiết phải có A ở đây, nhưng các phần mềm được xây dựng để xử lý điều này là rất tệ. Đây là những gì tôi sẽ làm cho bây giờ.
Jeff

3
Tại sao ngày trong cột kiểm tra không khớp với cột đầu tiên? Có, bây giờ là loại ngày tháng nhưng ngày và tháng không khớp với nhau. Có một lý do?
Jenks

1
kiểm tra đưa ra các giá trị không chính xác cho ngày. Đây không phải là câu trả lời đúng.
Shehryar

1
Bất kỳ giải pháp nào với UDF không phải là một câu trả lời, hầu như không phải là một giải pháp thay thế. Tôi không nghĩ rằng, có nhiều trường hợp sử dụng mà bạn không thể thực hiện bằng cách kết hợp chính PSF và .transform ().
sumon c

28

Phương pháp strptime () không hoạt động với tôi. Tôi nhận được một giải pháp khác sạch hơn, sử dụng cast:

from pyspark.sql.types import DateType
spark_df1 = spark_df.withColumn("record_date",spark_df['order_submitted_date'].cast(DateType()))
#below is the result
spark_df1.select('order_submitted_date','record_date').show(10,False)

+---------------------+-----------+
|order_submitted_date |record_date|
+---------------------+-----------+
|2015-08-19 12:54:16.0|2015-08-19 |
|2016-04-14 13:55:50.0|2016-04-14 |
|2013-10-11 18:23:36.0|2013-10-11 |
|2015-08-19 20:18:55.0|2015-08-19 |
|2015-08-20 12:07:40.0|2015-08-20 |
|2013-10-11 21:24:12.0|2013-10-11 |
|2013-10-11 23:29:28.0|2013-10-11 |
|2015-08-20 16:59:35.0|2015-08-20 |
|2015-08-20 17:32:03.0|2015-08-20 |
|2016-04-13 16:56:21.0|2016-04-13 |

7
Cảm ơn, cách tiếp cận này đã hiệu quả với tôi! Trong trường hợp ai đó muốn chuyển đổi một chuỗi như 2008-08-01T14:45:37Zmột dấu thời gian thay vì ngày, df = df.withColumn("CreationDate",df['CreationDate'].cast(TimestampType()))hoạt động tốt ... (Spark 2.2.0)
Gaurav

1
Tôi đã thử tùy chọn này trong số nhiều tùy chọn từ AWS Glue pyspark, hoạt động giống như sự quyến rũ!
Abhi

11

Trong bản cập nhật của câu trả lời được chấp nhận, bạn không thấy ví dụ cho to_datehàm, vì vậy một giải pháp khác sử dụng nó sẽ là:

from pyspark.sql import functions as F

df = df.withColumn(
            'new_date',
                F.to_date(
                    F.unix_timestamp('STRINGCOLUMN', 'MM-dd-yyyy').cast('timestamp')))

1
làm một to_date đơn giản () không làm việc, đây là câu trả lời đúng
ski_squaw

6

có thể không có quá nhiều câu trả lời nên tôi nghĩ hãy chia sẻ mã của tôi để có thể giúp ai đó

from pyspark.sql import SparkSession
from pyspark.sql.functions import to_date

spark = SparkSession.builder.appName("Python Spark SQL basic example")\
    .config("spark.some.config.option", "some-value").getOrCreate()


df = spark.createDataFrame([('2019-06-22',)], ['t'])
df1 = df.select(to_date(df.t, 'yyyy-MM-dd').alias('dt'))
print df1
print df1.show()

đầu ra

DataFrame[dt: date]
+----------+
|        dt|
+----------+
|2019-06-22|
+----------+

đoạn mã trên để chuyển đổi thành ngày tháng nếu bạn muốn chuyển đổi ngày giờ thì hãy sử dụng to_timestamp. cho tôi biết nếu bạn có bất kỳ nghi ngờ.


1

Thử cái này:

df = spark.createDataFrame([('2018-07-27 10:30:00',)], ['Date_col'])
df.select(from_unixtime(unix_timestamp(df.Date_col, 'yyyy-MM-dd HH:mm:ss')).alias('dt_col'))
df.show()
+-------------------+  
|           Date_col|  
+-------------------+  
|2018-07-27 10:30:00|  
+-------------------+  

7
Bạn có thể xem xét việc xây dựng chi tiết cách trả lời của bạn cải thiện dựa trên những gì đã được cung cấp và chấp nhận.
chb
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.