iT邦幫忙

2023 iThome 鐵人賽

DAY 8
0
AI & Data

30天胡搞瞎搞學會pyspark系列 第 8

[ Day 8 ] - Pyspark | 清理 - 時間篇 - 2 Timestamp 轉換 : User Defined Function 的出現

  • 分享至 

  • xImage
  •  

在多數情況下,使用to_timestamp(),幾乎可以解決掉所有的時間轉換問題,但Data Cleaning 是永遠不會讓你好過的,那這時候可以怎麼做呢?
這時候user define function 就出來了
為了這種狀況,救世主就出現了,我們可以自己定義想要的處理方式,並加入各種各樣的邏輯,然後就可以完美的處理資料啦!

user define function 其實很簡單,基本上就在你原本的function外面加上udf(),就可以實現你的user defined function 了

那我們接下來看看要怎麼實作這個時間轉換的問題吧

當你的一個data set 中可能有很多不同的時間format(MM/DD/YYYY,DD/MM/YYYY)

就可以參考下列做法去做轉換,推薦於使用spark3.0以上版本,因為spark3.0以上版本的timestamp format機制較於嚴格,常常會有因為format已經無法符合現行的架構出現的error

所以這時候我們就可以求助於user defined function,
這時候我們需要import time去做處理
可以借助python中的time.strptime(date, "%m/%d/%Y %I:%M:%S %p")
去給定目前的時間格式,接下來Do Re Mi So ~
啊不小心透露年齡了,簡單來說這樣就可以快速又簡單地完成你的時間轉換喔!
下面是sample code的部分~

def timestamp_change(date,formatString):
    """Timestamp handle 
    change multiple format to 'yyyy-MM-dd hh:mm:ss'
    1. MM/DD/YYYY and PM/AM e.g.Format: 1/17/2023 10:06:18 PM
    2. MM/DD/YYYY           e.g.Format: 1/17/2023
    3. DD/MM/YYYY.          e.g.Format: 17/1/2023.
    4. DD/MM/YYYY           e.g.Format: 17/1/2023
    Args:
        date : date string
        formatString : like MM/DD/YYYY or DD/MM/YYYY
    Return:
        format timestamp
    """
    if date is None:
        return date
    split_date = date.split('/')
    ## means strange data ,so we need to use another way to fixed 
    if len(split_date) == 1:
        return date
    else :
        if formatString == 'MM/DD/YYYY':
            if re.search("[A-z]",split_date[2]) != None: 
                time_obj_default = time.strptime(date, "%m/%d/%Y %I:%M:%S %p")
                mon = str(time_obj_default.tm_mon)
                day = str(time_obj_default.tm_mday)
                hour = str(time_obj_default.tm_hour)
                minute = str(time_obj_default.tm_min)
                sec = str(time_obj_default.tm_sec)
                if len(mon) == 1:
                    mon ='0'+mon
                if len(day) == 1:
                    day ='0'+day
                if len(hour) == 1:
                    hour ='0'+hour
                if len(minute) == 1:
                    minute ='0'+minute
                if len(sec) == 1:
                    sec ='0'+sec
                return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' '+hour+':'+minute+':'+sec)
            else:
                date =date.split('.')[0]
                time_obj_default = time.strptime(date, "%m/%d/%Y")
                mon = str(time_obj_default.tm_mon)
                day = str(time_obj_default.tm_mday)
                if len(mon) == 1:
                    mon ='0'+mon
                if len(day) == 1:
                    day ='0'+day
                return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' 00:00:00')
        elif formatString == 'DD/MM/YYYY':
            if re.search("[A-z]",split_date[2]) != None: 
                time_obj_default = time.strptime(date, "%d/%m/%Y %I:%M:%S %p")
                mon = str(time_obj_default.tm_mon)
                day = str(time_obj_default.tm_mday)
                hour = str(time_obj_default.tm_hour)
                minute = str(time_obj_default.tm_min)
                sec = str(time_obj_default.tm_sec)
                if len(mon) == 1:
                    mon ='0'+mon
                if len(day) == 1:
                    day ='0'+day
                if len(hour) == 1:
                    hour ='0'+hour
                if len(minute) == 1:
                    minute ='0'+minute
                if len(sec) == 1:
                    sec ='0'+sec
                return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' '+hour+':'+minute+':'+sec)
            else:
                date =date.split('.')[0]
                time_obj_default = time.strptime(date, "%d/%m/%Y")
                mon = str(time_obj_default.tm_mon)
                day = str(time_obj_default.tm_mday)
                if len(mon) == 1:
                    mon ='0'+mon
                if len(day) == 1:
                    day ='0'+day
                return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' 00:00:00')

timestamp_change_udf = udf(lambda x,y: timestamp_change(x,y),StringType()) 

##接下來你只要直接去呼叫你的function就可以成功轉換囉
df = df.withColumn('Date_of_open',to_timestamp(timestamp_change_udf('Date_of_open','formatString')))

希望今天的內容對大家有幫助!


上一篇
[ Day 7 ] - Pyspark | 清理 - 時間篇 - 1 : Timestamp 轉換 : to_timestamp()
下一篇
[ Day 9 ] - Pyspark | 清理 - 字串篇-1 - 切切切 : split(), substr()
系列文
30天胡搞瞎搞學會pyspark30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言