7

这个问题询问 R 中按时间段聚合的问题,pandas 称之为重采样。最有用的答案使用 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
4

4 回答 4

8

我不知道你为什么要为此使用 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 的请求这一事实证明了这一点;-))。


OP 中链接到的其他问题的答案未涵盖的内容是. 拆分at并将函数应用于每个组。您可以使用该函数找到对给定任务有用的端点。例如,如果您有一个 xts 对象,那么将为您提供每个月最后一行的行号。 利用它来拆分 xts 对象 -将返回 xts 对象列表,其中每个组件用于不同的月份。split.xtsperiod.applyxtsendpointsendpointsxendpoints(x, "months")split.xtssplit(x, "months")

虽然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 在这个问题中的最佳用途是将“日期”字符串解析为 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"))
于 2013-08-04T18:49:57.500 回答
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 包中的 ("fast read") 一步将 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")] 
于 2013-08-04T19:18:26.780 回答
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
于 2013-08-04T19:21:59.357 回答
1

这是请求的lubridate解决方案,我也将其添加到链接的问题中。它结合使用lubridatezoo 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一样甜美。

于 2015-09-21T21:25:49.513 回答