R語言與格式,日期格式,格式轉化的操作
R語言的基礎包中提供瞭兩種類型的時間數據,一類是Date日期數據,它不包括時間和時區信息,另一類是POSIXct/POSIXlt類型數據,其中包括瞭日期、時間和時區信息。
基本總結如下:
日期data,存儲的是天;
時間POSIXct 存儲的是秒,POSIXlt 打散,年月日不同;
日期-時間=不可運算。
一般來講,R語言中建立時序數據是通過字符型轉化而來,但由於時序數據形式多樣,而且R中存貯格式也是五花八門,例如Date/ts/xts/zoo/tis/fts等等。lubridate包(後續有介紹,應用四),timeDate包,都有用。
常見的格式:
as.numeric | 轉化為數值型 |
as.logic | 轉化為邏輯型 |
as.complex | 轉化為復數型 |
as.character | 轉化為字符型 |
as.array | 轉化為數組 |
as.data.frame | 轉化為數據框 |
d<-as.character(z) #將數值向量z<-(0:9)轉化為字符向量c("0", "1", "2", ..., "9")。 as.integer(d) #將d轉化為數值向量 e <- numeric() #產生一個numeric型的空向量e a=data.frame(a) #變成R的數據框 factor() #變成因子 可以用levels()來看因子個數
在data.frame中,是可以實現數據集重命名的,比如data.frame(x=iris,y=cars),
也可以實現橫向、縱向重命名,data.frame(x=iris,y=cars,row.names=iris)
後續加更內容
應用1——如何通過生日計算年齡
應用2——日期分組
應用三——生成按天的時間序列並進行回歸
應用四:靈活處理時間數據—lubridate包(來源TipDM)
應用五:如何在循環、函數中,輸出實時時間消耗?
時間的標準格式
mydate = as.POSIXlt('2005-4-19 7:01:00') names(mydate)
默認情況下,日期之前是以/或者-進行分隔,而時間則以:進行分隔;
輸入的標準格式為:日期 時間(日期與時間中間有空隔隔開)
時間的標準格式為:時:分 或者 時:分:秒;
如果輸入的格式不是標準格式,則同樣需要使用strptime函數,利用format來進行指定。
一、日期型數據——data
1、as.Data函數
在R中自帶的日期形式為:as.Date();以數值形式存儲;
對於規則的格式,則不需要用format指定格式;如果輸入的格式不規則,可以通過format指定的格式讀入;其中以1970-01-01定義為第0天,之後的年份會以距離這天來計算。
> x<-as.Date("1970-01-01") > unclass(x) [1] 0 > > unclass(as.Date("1970-02-01")) #19700201代表第31天 [1] 31
代碼解讀:unclass可以將日期變成以天來計數,比如1970-02-01輸出的31,就代表著距離1970-01-01有31天。
as.data中的參數格式:年-月-日或者年/月/日;如果不是以上二種格式,則會提供錯誤——錯誤於charTo按照Date(x) : 字符串的格式不夠標準明確;
例如這樣的數據格式,就常常報錯。
19:15.
顯示為:2011/1/1 19:15
as.Date('23-2013-1',format='%d-%Y-%m') #其中這個%d%Y可以節選其中一個 #%Y%y 大寫代表年份四位數,小寫代表年份二位數,要註意
2、%d%y%m-基本格式
格式 |
意義 |
%d |
月份中當的天數 |
%m |
月份,以數字形式表示 |
%b |
月份,縮寫 |
%B |
月份,完整的月份名,指英文 |
%y |
年份,以二位數字表示 |
%Y |
年份,以四位數字表示 |
#其它日期相關函數
weekdays()取日期對象所處的周幾;
months()取日期對象的月份;
quarters()取日期對象的季度。
二、時間型——POSIXct與POSIXlt
POSIXct 是以1970年1月1號開始的以秒進行存儲,如果是負數,則是1970-01-01年以前;正數則是1970年以後。
POSIXlt 是以列表的形式存儲:年、月、日、時、分、秒,作用是打散時間;
1、POSIXlt 格式
主要特點:作用是打散時間,把時間分成年、月、日、時、分、秒,並進行存儲。
可以作為時間篩選的一種。
> today<-Sys.time() > unclass(as.POSIXlt(today)) $sec [1] 53.27151 $min [1] 38 $hour [1] 20 $mday [1] 6 $mon [1] 5 $year [1] 116 $wday [1] 1 $yday [1] 157 $isdst [1] 0 $zone [1] "CST" $gmtoff [1] 28800 attr(,"tzone") [1] "" "CST" "CDT"
代碼解讀:unclass將時間打散。
2、POSIXct 格式
主要特點:以秒進行存儲。
> today<-Sys.time() > today [1] "2016-06-06 20:42:22 CST" > unclass(as.POSIXct(today)) [1] 1465216942
解讀:比如今天,unclass之後,代表今天2016-06-06距離1970-01-01為1465216942秒。
#GMT代表時區,德意志時間,CST也代表時區
三、時間運算
1、基本運算函數
Sys.Date() #字符串類型 typeof(Sys.Date()) #系統日期類型
2、直接加減
相同的格式才能相互減,不能加。二進列的+法對”Date”、”POSIXt”對象不適用。
> as.Date("2011-07-01") - as.Date(today) Time difference of -1802 days > as.POSIXct(today)-as.POSIXct(as.Date("2012-10-25 01:00:00")) Time difference of 1320.529 days > as.POSIXlt(today)-as.POSIXlt(as.Date("2012-10-25 01:00:00")) Time difference of 1320.529 days
相互減之後,一般結果輸出的天數。
3、difftime函數——計算時差
不同格式的時間都可以進行運算。並且可以實現的是計算兩個時間間隔:秒、分鐘、小時、天、星期。
但是不能計算年、月、季度的時間差。
gtd <- as.Date("2011-07-01") difftime(as.POSIXct(today), gtd, units="hours") #隻能計算日期差,還可以是“secs”, “mins”, “hours”, “days”
4、format函數——提取關鍵信息
> today<-Sys.time() > format(today,format="%B-%d-%Y") [1] "六月-06-2016"
format函數可以將時間格式,調節成指定時間樣式。format(today,format=”%Y”)其中的format可以自由調節,獲取你想要的時間信息。
並且format函數可以識別as.Data型以及POSIXct與POSIXlt型,將其日期進行提取與之後要討論的split類型。
> today<-Sys.time() > format(as.Date(today),format="%Y") [1] "2016" > format(as.POSIXlt(today),format="%Y") [1] "2016" > format(as.POSIXct(today),format="%Y") [1] "2016"
但是format出來的時間不能直接做減法,會出現錯誤: non-numeric argument to binary operator
5、strptime函數
該函數是將字符型時間轉化為 “POSIXlt” 和”POSIXct”兩類。跟format比較相似。
strptime之後的時間是可以直接做減法,因為直接是”POSIXlt” 和”POSIXct”格式瞭。
> strptime("2006-01-08 10:07:52", "%Y-%m-%d")-strptime("2006-01-15 10:07:52", "%Y-%m-%d") Time difference of -7 days > class(strptime("2006-01-08 10:07:52", "%Y-%m-%d")) [1] "POSIXlt" "POSIXt"
四、遇見的問題
1、常常報錯。
錯誤於charTo按照Date(x) : 字符串的格式不夠標準明確。這個錯誤經常出現,我本來的數據格式是
19:15.
後來換成“2011/1/1”這樣的就不會報錯瞭,需要數據庫自動改變。
#幾種錯誤匯總 dtV<-data.frame(as.POSIXct(a$b,format="%d.%m.%Y")) #錯,讀出來都是NA as.Date(a$b, "%Y年%m月%d日") #錯,讀不出來 as.POSIXct(strptime(a$b, "%Y-%m-%d")) #讀不出來 #轉化成xts格式也讀不出來 install.packages("xts") library(xts) as.xts(read.zoo("time.csv",header=T)) a <- as.xts(a, descr='my new xts object') as.xts(read.zoo("a.csv",header=T)) #錯 #轉化成數值型也不對 c=as.numeric(sales[,2])
2、excel另存為csv時發生的錯誤。
一位網友說:我以前是在excel裡另存為csv格式,百度上說CSV檔如果以EXCEL開啟,由於計算機檔案數據轉換的原因,會將其CRC之數值改做科學記號方式儲存,而造成檔案中的 CRC值發生錯誤。
應用1——如何通過生日計算年齡
1、format函數
timeformat<-function(x){ format(as.POSIXct(x),format="%Y") } sapply(as.Date(data$birthdate),timeformat)
format隻能一個一個操作,可以先寫成函數,然後計算得出年份,之後用如今的年份相減得到年齡。
2、字符型——strsplit
先轉化為字符型,然後進行分割。
data.frame(sapply(as.character(data$birthdate),function(x){strsplit(x,"-")[[1]][1]}))
註意,其中strsplit中的”-“,根據具體時間格式情況來定義。
應用2——日期分組
一種按照日期范圍——例如按照周、月、季度或者年——對其進行分組的超簡便處理方式:R語言的cut()函數。
假設vector中存在以下示例數據:
vDates <- as.Date(c("2013-06-01", "2013-07-08", "2013-09-01", "2013-09-15")) #as.Data()函數的作用非常重要;如果沒有它,R語言會認為以上內容僅僅是數字串而非日期對象 [1] "2013-06-01" "2013-07-08" "2013-09-01" "2013-09-15" vDates.bymonth <- cut(vDates, breaks = "month") [1] 2013-06-01 2013-07-01 2013-09-01 2013-09-01 Levels: 2013-06-01 2013-07-01 2013-08-01 2013-09-01 Dates <- data.frame(vDates, vDates.bymonth)
應用三——生成按天的時間序列並進行回歸
如果是生成簡單的年度,月度數據,ts函數可以滿足,但是如果生成的是每天。因為有閏年緣故,所以zoo包可以很好地解決這個問題。
還有筆者在做一個簡單的時間序列回歸時候,疑惑:
做關於時間序列的ols最小二乘法回歸方程,按年來好說,但是如果是按天,如果進行計算呢?
1、把天變成一排規律遞增的數字來代替;
2、ts函數變化之後,也是變成一個遞增的數字。
以上兩種,做的結果都一樣,所以沒有什麼太大的區別。
關於ts函數by day每一天的時間序列生成,該如何呢?
n=30 t<-ts(1:n,frequency=1,start=as.Date("2010-01-09"))
生成一個按天的時間序列。
應用四:靈活處理時間數據—lubridate包(來源TipDM)
lubridate包是由Garrett Grolemund 和 Hadley Wickham寫的,可以靈活地處理時間數據。lubridate包主要有兩類函數,一類是處理時點數據(time instants),另一類是處理時段數據(time spans)。
1、時點類函數
主要包括解析、抽取、修改。
2、時段類函數
可以處理三類對象,分別是:
interval:最簡單的時段對象,它由兩個時點數據構成。
duration:去除瞭時間兩端的信息,純粹以秒為單位計算時段的長度,不考慮閏年和閏秒,它同時也兼容基本包中的difftime類型對象。
period:以較長的時鐘周期來計算時段長度,它考慮瞭閏年和閏秒,適用於長期的時間計算。以2012年為例,duration計算的一年是標準不變的365天,而period計算的一年就會變成366天。
有瞭時點和時段數據,就可以進行各種計算瞭。
3、時區信息
lubridate包提供瞭三個函數:
tz:提取時間數據的時區
with_tz:將時間數據轉換為另一個時區的同一時間
force_tz:將時間數據的時區強制轉換為另一個時區
應用五:如何在循環、函數中,輸出實時時間消耗?
想知道循環中進行到哪裡?這樣可以合理安排函數進程。那麼怎麼辦呢?
第一辦法:使用Rstudio 1.0版本,裡面有一個Profiling with profvis,可以很好的對你函數每一步的耗時進行參看。
R︱Rstudio 1.0版本嘗鮮(R notebook、下載鏈接、sparkR、代碼時間測試profile)
當然,這個不能實時輸出內容。
第二辦法:利用difftime函數
t1 = Sys.time() for (i in 1:5){ a=a+1 b=a*a print(difftime(Sys.time(), t1, units = 'sec')) }
先預設當前時間,然後用difftime+print方式,循環輸出。
應用六:因子型數據轉化為數值型
因子型轉化的時候會發現,譬如10000這個數字,會變為6,也就是因子型裡面對應的次序,這樣並不是我們想要的。所以,可以先變為字符型as.character:
as.numeric(as.character(data))
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。如有錯誤或未考慮完全的地方,望不吝賜教。
推薦閱讀:
- None Found