This question询问R中的时间段聚合,pandas调用重新采样。最有用的答案是使用XTS包在给定的时间段内分组,应用一些函数,如sum()或mean()。
其中一条评论表明,在lubridate中有类似的东西,但没有详细说明。有人可以使用lubridate提供一个惯用的例子吗?我已经阅读了几次相关的rubridate小插图,可以想象一下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
答案 0 :(得分:7)
我不知道你为什么要使用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
是最简单的(事实证明其他Answers也忽略了你的请求)使用lubridate ;-))。
Answer与OP中链接的另一个Question未涵盖的内容为split.xts
。 period.apply
在xts
分割endpoints
并将功能应用于每个组。您可以使用endpoints
函数找到对给定任务有用的端点。例如,如果您有一个xts对象x
,那么endpoints(x, "months")
将为您提供每个月最后一行的行号。 split.xts
利用它来分割xts对象 - split(x, "months")
将返回一个xts对象列表,其中每个组件的月份不同。
虽然split.xts()
和endpoints()
主要用于xts
个对象,但它们也适用于其他一些对象,包括基于简单时间的向量。即使您不想使用xts对象,您仍然可以找到endpoints()
的用途,因为它的便利性或速度(在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
我认为lubridate在这个问题中的最佳用途是将“Date”字符串解析为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"))
答案 1 :(得分: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
注意,您还可以使用data.table包中的fread()
(“快速读取”)将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")]
答案 2 :(得分:2)
使用plyr包中的ddply
:
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
答案 3 :(得分:1)
这是请求的 lubridate 解决方案,我也将其添加到链接的问题中。它使用 lubridate 和 zoo aggregate()的组合进行这些操作:
ts.month.sum <- aggregate(zoo.ts, month, sum)
ts.daily.mean <- aggregate(zoo.ts, day, mean)
ts.mins.mean <- aggregate(zoo.ts, minutes, mean)
显然,您需要先将数据转换为zoo()对象,这很容易。您还可以使用yearmon()或yearqtr(),或者的自定义函数拆分和应用。这种方法在语法上比 pandas 更好。