#分享 R語言-時間資料處理

2019年12月18日 19:58
在R資料處理之中,時常會需要遇到時間格式的處理 實驗數據、股市資料、氣候資訊隨著時間不斷的流逝 各式資料也不斷的生成的情況下時間的判讀就顯得重要 多數時候取得的時間資料就是一長串的數字 如何讓程式讀取時間資料以及對時間資料的處理是今天這文章的重點 因文章包含大量範例不方便在Dcard上展示 有興趣的可以參考下列連結
目前已開放hackmd的協作功能 若有興趣或是覺得需要補充的都可以前往編輯 簡單目錄 : 時間資料處理 取得時間資訊 取得特定日期或時間資訊 單日期之文字格式轉換 包含時間資料之文字格式轉換 時間格式之運算 lubridate套件更靈活處理R時間格式 判斷日期日期 簡單的函數來獲取日期或時間物件 時間的四捨五入與條件捨去、進位 ***************************************** # 取得時間資訊 ```R= Sys.Date() #當前日期 lubridate::today() date() #當前系統日期和時間 Sys.time() #當前系統日期和時間 lubridate::now() Sys.timezone() #有關時區的信息將返回當前時區的名稱 ``` :::success [1] "2019-12-13" [1] "Fri Dec 13 21:50:58 2019" [1] "2019-12-13 21:52:04 CST" [1] "Asia/Taipei" ::: ```R=+ head(OlsonNames()) #取得有關時區的信息、時區的名稱 ``` :::success [1] "Africa/Abidjan" "Africa/Accra" "Africa/Addis_Ababa" "Africa/Algiers" [5] "Africa/Asmara" "Africa/Asmera" ::: ## 取得特定日期或時間資訊 :::danger format(date,format): ::: ```R= #輸出年份: format(Sys.Date(),format="%Y") format(Sys.Date(),format="%y") #輸出月份: format(Sys.Date(),format="%b") format(Sys.Date(),format="%B") format(Sys.Date(),format="%m") #輸出星期: format(Sys.Date(),format="%A") format(Sys.Date(),format="%a") #摻雜文字輸出: format(Sys.Date(),format="%Y年%m月%d日") ``` :::success #輸出年份: [1] "2019" [1] "17" [1] "19" #輸出月份: [1] "十二月" [1] "十二月" [1] "12" #輸出星期: [1] "星期五" [1] "週五" #摻雜文字輸出: [1] "2019年12月13日" ::: 也可以使用其他內置函數處理 ```R= weekdays(Sys.Date()) #取得日期物件的星期資料 months(Sys.Date()) #取得日期物件的月份 days(Sys.Date()) #取得日期物件日期 quarters(Sys.Date()) #取得日期物件的季度 ``` # 單日期之文字格式轉換 :::danger as.Date(x, format) ::: format參數用於指定輸入的格式,常用的日期格式符號是: |%y|兩個數字表示的年份(00-99),不帶世紀,例如,數值是18,格式%y,表示2018年| |---|---| |%Y|四位數字表示的年份(0000-9999)| |%m|兩個數字的月份,取值範圍是01-12,或1-12| |%d|月份中的天,取值範圍是01-31| |%e|月份中的天,取值範圍是1-31| |%b|縮寫的月份(Jan,Feb,Mar等)| |%B|英語月份全名(January、February 、March等)| |%a|縮寫的星期名(Mon、Tue、Wed、Thur、Fri、Sat、Sun)| |%A|星期全名| ```R= as.Date('2019-12-02', '%Y-%m-%d') as.Date('12/02 2019', '%m/%d %Y') ``` :::success [1] "2019-12-02" [1] "2019-12-02" ::: # 包含時間資料之文字格式轉換 :::danger as.POSIXlt(x, format) as.POSIXct(x, format) ::: **POSIXlt** 是以列表的形式分別儲存年、月、日、时、分、秒資料 **POSIXct** 則是以1970年1月1號開始計算過了幾秒,如果是負數,則是1970-01-01年以前; 正數則是1970年以後。 | %H|小時(24小時制)| |---|---| |%I|小時(12小時制)| |%p|對於12小時制,指定上午(AM)或下午(PM)| |%M|分鐘| |%S|秒| ```R= as.POSIXlt('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S") as.POSIXct('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S") ``` :::success [1] "2019-12-13 22:12:00 CST" [1] "2019-12-13 22:12:00 CST" ::: 比如2019/12/13 22:12:00相比於1970年1月1號經過了1576246320秒 ```R=+ unclass(as.POSIXct('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S")) ``` :::success [1] 1576246320 attr(,"tzone") [1] "" ::: ```R=+ unclass(as.POSIXlt('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S")) ``` :::success $sec [1] 0 $min [1] 12 $hour [1] 22 $mday [1] 13 $mon [1] 11 $year [1] 119 $wday [1] 5 $yday [1] 346 $isdst [1] 0 $zone [1] "CST" $gmtoff [1] NA ::: # 時間格式之運算 不同時間格式間可以進行相減但無法進行相加 ```R= D1 <- as.POSIXlt('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S") D2 <- as.POSIXlt('2019/12/13 10:12:00', format="%Y/%m/%d %H:%M:%S") D3 <- as.POSIXct('2019/12/13 22:12:00', format="%Y/%m/%d %H:%M:%S") D4 <- as.POSIXct('2019/12/13 10:12:00', format="%Y/%m/%d %H:%M:%S") D1-D2 D1-D3 D1-D4 ``` :::success Time difference of 12 hours Time difference of 0 secs Time difference of 12 hours ::: ```R=+ D1+D4 D1+D2 ``` :::success Error in `+.POSIXt`(D1, D4) : binary '+' is not defined for "POSIXt" objects Error in `+.POSIXt`(D1, D2) : binary '+' is not defined for "POSIXt" objects ::: 而加上數字則為秒數增加 `D1 + 1` [1] "2019-12-13 22:12:01 CST" `D1 + 60` [1] "2019-12-13 22:36:00 CST" `D1 + 60 * 60` [1] "2019-12-13 23:12:00 CST" `D1 + 60 * 60 * 24` [1] "2019-12-14 22:12:00 CST" `D1 + 60 * 60 * 24 * 30` [1] "2020-01-12 22:12:00 CST" 時間格式間計算時間差可以使用difftime() :::danger difftime(time1, time2, tz,units = c("auto", "secs", "mins", "hours","days", "weeks")) ::: ```R= D1 <- as.Date("2019/12/16") D2 <- as.Date("2012/11/17") difftime(D1, D2, units ="secs") ``` :::success Time difference of 223344000 secs ::: # lubridate套件更靈活處理R時間格式 ```R= install.packages("lubridate") #安裝套件 library(lubridate) #讀取套件 ``` lubridate主要有判斷、提取、修改等功能 ## 判斷日期日期 lubridate以y代表yeard, m代表month, d代表day,透過y-m-d的不同排序來判斷時間格式 ```R=+ ymd("2019-12-16") ymd("2019/12/16") ymd("2019_12_16") ymd("19_12_16") mdy("121619") dmy(161219) ``` :::success [1] "2019-12-16" [1] "2019-12-16" [1] "2019-12-16" [1] "2019-12-16" [1] "2019-12-16" [1] "2019-12-16" ::: 再搭配h表示小時,m為分鐘與s為秒可以組成dmy_hms、ymd_hms等函數來判斷包含時間之格式 ```R=+ ymd_hms("2019_12_16 12:01:56") ymd_hm("2019_12_16 12:01") ymd_h("2019_12_16 12") mdy_hms("121619 12:01:56") ``` :::success [1] "2019-12-16 12:01:56 UTC" [1] "2019-12-16 12:01:00 UTC" [1] "2019-12-16 12:00:00 UTC" [1] "2019-12-16 12:01:56 UTC" ::: ## 簡單的函數來獲取日期或時間物件 :::danger year() #取得年份 month() #取得月份 mday() #取的日期 hour() #取得小時數 minute() #取得分鐘數 second() #取得秒數 ::: ```R= D5 <- mdy_hms("121619 12:01:56") year(D5) #取得年份 month(D5) #取得月份 mday(D5) #取的日期 hour(D5) #取得小時數 minute(D5) #取得分鐘數 second(D5) #取得秒數 ``` :::success [1] 2019 [1] 12 [1] 16 [1] 12 [1] 1 [1] 56 ::: :::danger yday() #判斷日期為這一年得第幾天 wday() #判斷日期星期 week() #判斷日期為這一年得第幾周 days_in_month() #取得日期當月的最大天數 ::: ```R=+ yday(D5) #判斷日期為這一年得第幾天 wday(D5) #判斷日期星期 week(D5) #判斷日期為這一年得第幾周 days_in_month(D5) #取得日期當月的最大天數 ``` :::success [1] 350 [1] 2 [1] 50 Dec 31 ::: ## 時間的四捨五入與條件捨去、進位 :::danger round_date(x, unit) #將時間依據單位四捨五入 floor_date(x, unit) #將時間依據單位條件捨去 ceiling_date(x, unit) #將時間依據單位條件進位 **可使用單位Valid base units are second, minute, hour, day, week, month, bimonth(雙月), quarter(季度), season(季節), halfyear(半年) and year** ::: ```R=+ round_date(D5, unit = "day") #將時間四捨五入至天數 floor_date(D5, unit = "day") #將時間條件捨去至天數 ceiling_date(D5, unit = "day") #將時間條件進位至天數 ``` :::success [1] "2019-12-17 UTC" [1] "2019-12-16 UTC" [1] "2019-12-17 UTC" ::: 參考資料 >[lubridate.tidyverse](
>[Dates and times with lubridate : : CHEAT SHEET(速查表)](
>[R for Data Science](
[name=Garrett Grolemund、Hadley Wickham]
9
回應 6
文章資訊
共 6 則留言
您好,想詢問您是否知道 如果想把日值的資料轉換成一個月份的平均值然後建立資料表該怎麼做嗎 我遇到瓶頸了..
我只有目前卡關的狀況圖耶@@因為題目是自己想的,我的題目是把日資料用成月平均跟年平均 這是嘗試著做出來的資料表,但我想讓它把1號到31號也平均成為一行台北市一月份的總平均..
B3 你是希望將一月份到十二月做平均嗎? 在lubridate套件中有month()可以提取月份 在將每月分做平均? 看起來是用sql處理 這部分我比較不熟悉沒辦法幫你 可以試著將寫一篇問題在板上發問
匿名
這則留言已被本人刪除
2020年1月5日 23:05
已經刪除的內容就像 Dcard 一樣,錯過是無法再相見的!
想請問你~可以在一個日子中的一堆時間內 取出我要某一個時間段的時間嗎 例如:整天的時間資料(以秒變動)然後我要擷取下午一點內的所有資料這樣?