2013-08-04 21 views
6

This question詢問R中的時間段聚合,大熊貓稱爲重新採樣。最有用的答案是使用XTS包在給定時間段內進行分組,應用sum()或mean()等函數。lubridate中的時間段的聚合

其中一條評論建議在lubridate中有類似的內容,但沒有詳細說明。有人可以使用lubridate提供一個慣用的例子嗎?我已經閱讀了幾次潤溼的小插圖,並可以想象一些lubridate和plyr的組合,但是我想確保沒有更簡單的方法,我錯過了。

爲了讓這個例子更真實,讓我們說,我想自行車從這個數據集向北行駛的日常總和:

library(lubridate) 
library(reshape2) 

bikecounts <- read.csv(url("http://data.seattle.gov/api/views/65db-xm6k/rows.csv?accessType=DOWNLOAD"), header=TRUE, stringsAsFactors=FALSE) 
names(bikecounts) <- c("Date", "Northbound", "Southbound") 

的數據是這樣的:

> head(bikecounts) 
        Date Northbound Southbound 
1 10/02/2012 12:00:00 AM   0   0 
2 10/02/2012 01:00:00 AM   0   0 
3 10/02/2012 02:00:00 AM   0   0 
4 10/02/2012 03:00:00 AM   0   0 
5 10/02/2012 04:00:00 AM   0   0 
6 10/02/2012 05:00:00 AM   0   0 

回答

6

我不知道爲什麼你會爲此使用lubridate。如果你只是在尋找比XTS少真棒東西,你可以試試這個

tapply(bikecounts$Northbound, as.Date(bikecounts$Date, format="%m/%d/%Y"), sum) 

基本上,你只需要通過split日期,然後應用的功能。


lubridate可用於創建拆分應用問題的分組因子。因此,舉例來說,如果你想每個月的總和(忽略年)

tapply(bikecounts$Northbound, month(mdy_hms(bikecounts$Date)), sum) 

但是,它只是使用基礎R函數的包裝,並在OP的情況下,我認爲基礎R功能as.Date是最簡單的(正如其他答案也忽略了使用lubridate的請求所證明的那樣;-))。

這是不包括在 Answer在OP鏈接到其他 Question

東西是split.xtsperiod.applyendpoints處拆分xts並將函數應用於每個組。您可以使用endpoints函數查找對於給定任務有用的端點。例如,如果您有一個xts對象,則x,然後endpoints(x, "months")會爲您提供每月最後一行的行號。 split.xts利用它來分割一個xts對象 - split(x, "months")將返回一個xts對象的列表,其中每個組件在不同的月份。

儘管split.xts()endpoints()主要用於xts對象,但它們也可以用於其他一些對象,包括基於簡單時間的向量。即使你不想使用XTS對象,你還是會發現因爲它的方便或它的速度(用C實現的)

> split.xts(as.Date("1970-01-01") + 1:10, "weeks") 
[[1]] 
[1] "1970-01-02" "1970-01-03" "1970-01-04" 

[[2]] 
[1] "1970-01-05" "1970-01-06" "1970-01-07" "1970-01-08" "1970-01-09" 
[6] "1970-01-10" "1970-01-11" 

> endpoints(as.Date("1970-01-01") + 1:10, "weeks") 
[1] 0 3 10 

endpoints()用途,我認爲lubridate在這一問題的最佳用途是用於解析「日期」字符串到POSIXct對象中。即在這種情況下的mdy_hms功能。

這是一個xts解決方案,它使用lubridate來解析「日期」字符串。

x <- xts(bikecounts[, -1], mdy_hms(bikecounts$Date)) 
period.apply(x, endpoints(x, "days"), sum) 
apply.daily(x, sum) # identical to above 

對於這個特定的任務,xts也有一個優化的period.sum功能(Fortran語言編寫的),這是非常快

period.sum(x, endpoints(x, "days")) 
+0

這也很有用。很高興接受這個答案,如果共識是「不要使用lubridate;而是使用XTS」。這就是說,我聽到很多「使用lubridate」,所以我有點想知道什麼是大驚小怪! – Peter

+1

我傾向於同意@GSee。我_think_使用'lubridate'函數實現'ddply'-grouping變量的最簡單的'lubridate'方法只會是:'bikecounts $ date2 < - mdy_hms(x = bikecounts $ Date)'; 'bikecounts $ date3 < - round_date(x = bc $ date2,unit =「day」)'。 – Henrik

+0

偉大的每個人的答案集。支持這一個1.)糾正我的起始前提2.)提供一個基本的R例子3.)顯示什麼樣的潤溼版本,以及4.)解釋xts的好處。 – Peter

2

下面是使用data.table 導入CSV後一個選項:

library(data.table) 

# convert the data.frame to data.table 
bikecounts <- data.table(bikecounts) 

# Calculate 
bikecounts[, list(NB=sum(Northbound), SB=sum(Southbound)), by=as.Date(Date, format="%m/%d/%Y")] 

     as.Date NB SB 
    1: 2012-10-02 1165 773 
    2: 2012-10-03 1761 1760 
    3: 2012-10-04 1767 1708 
    4: 2012-10-05 1590 1558 
    5: 2012-10-06 926 1080 
---      
299: 2013-07-27 1212 1289 
300: 2013-07-28 902 1078 
301: 2013-07-29 2040 2048 
302: 2013-07-30 2314 2226 
303: 2013-07-31 2008 2076 

請注意,您也可以使用fread()(「快速讀取」)從data.table包中將CSV讀取到data.table中。 唯一的缺點是你需要手動轉換字符串的日期/時間。

eg: 
bikecounts <- fread("http://data.seattle.gov/api/views/65db-xm6k/rows.csv?accessType=DOWNLOAD", header=TRUE, stringsAsFactors=FALSE) 
setnames(bikecounts, c("Date", "Northbound", "Southbound")) 
bikecounts[, Date := as.POSIXct(D, format="%m/%d/%Y %I:%M:%S %p")] 
+1

這個答案也非常好,需要真正快速的聚合。沒有做基準測試,我敢打賭這種方法是最快的。 – Peter

+0

將data.table與lubridate或fasttime混合起來怎麼樣? – skan

2

使用ddply從plyr包:

library(plyr) 
bikecounts$Date<-with(bikecounts,as.Date(Date, format = "%m/%d/%Y")) 
x<-ddply(bikecounts,.(Date),summarise, sumnorth=sum(Northbound),sumsouth=sum(Southbound)) 


> head(x) 
     Date sumnorth sumsouth 
1 2012-10-02  1165  773 
2 2012-10-03  1761  1760 
3 2012-10-04  1767  1708 
4 2012-10-05  1590  1558 
5 2012-10-06  926  1080 
6 2012-10-07  951  1191 


> tail(x) 
      Date sumnorth sumsouth 
298 2013-07-26  1964  1999 
299 2013-07-27  1212  1289 
300 2013-07-28  902  1078 
301 2013-07-29  2040  2048 
302 2013-07-30  2314  2226 
303 2013-07-31  2008  2076 
1

這裏是請求lubridate解決方案,我也加入到該鏈接的問題。它採用lubridate動物園骨料()對這些操作的組合:

ts.month.sum <- aggregate(zoo.ts, month, sum) 

ts.daily.mean <- aggregate(zoo.ts, day, mean) 

ts.mins.mean <- aggregate(zoo.ts, minutes, mean) 

顯然,你需要首先將數據轉換成動物園()對象,這是很容易做到。您也可以使用yearmon()或yearqtr()或這兩個的自定義函數進行拆分和應用。這種方法在語法上與pandas一樣甜美。