10

假设我有几年的数据,如下所示

# load date package and set random seed
library(lubridate)
set.seed(42)

# create data.frame of dates and income
date <- seq(dmy("26-12-2010"), dmy("15-01-2011"), by = "days")
df <- data.frame(date = date, 
                 wday = wday(date),
                 wday.name = wday(date, label = TRUE, abbr = TRUE),
                 income = round(runif(21, 0, 100)),
                 week = format(date, format="%Y-%U"),
                 stringsAsFactors = FALSE)

#          date wday wday.name income    week
# 1  2010-12-26    1       Sun     91 2010-52
# 2  2010-12-27    2       Mon     94 2010-52
# 3  2010-12-28    3      Tues     29 2010-52
# 4  2010-12-29    4       Wed     83 2010-52
# 5  2010-12-30    5     Thurs     64 2010-52
# 6  2010-12-31    6       Fri     52 2010-52
# 7  2011-01-01    7       Sat     74 2011-00
# 8  2011-01-02    1       Sun     13 2011-01
# 9  2011-01-03    2       Mon     66 2011-01
# 10 2011-01-04    3      Tues     71 2011-01
# 11 2011-01-05    4       Wed     46 2011-01
# 12 2011-01-06    5     Thurs     72 2011-01
# 13 2011-01-07    6       Fri     93 2011-01
# 14 2011-01-08    7       Sat     26 2011-01
# 15 2011-01-09    1       Sun     46 2011-02
# 16 2011-01-10    2       Mon     94 2011-02
# 17 2011-01-11    3      Tues     98 2011-02
# 18 2011-01-12    4       Wed     12 2011-02
# 19 2011-01-13    5     Thurs     47 2011-02
# 20 2011-01-14    6       Fri     56 2011-02
# 21 2011-01-15    7       Sat     90 2011-02

我想总结每周(周日至周六)的“收入”。目前我执行以下操作:

Weekending 2011-01-01 = sum(df$income[1:7]) = 487
Weekending 2011-01-08 = sum(df$income[8:14]) = 387
Weekending 2011-01-15 = sum(df$income[15:21]) = 443

但是,我想要一种更强大的方法,它会自动按周求和。我不知道如何自动将数据子集为几周。任何帮助将非常感激。

4

7 回答 7

9

首先用于format将日期转换为周数,然后plyr::ddply()计算摘要:

library(plyr)
df$week <- format(df$date, format="%Y-%U")
ddply(df, .(week), summarize, income=sum(income))
     week income
1 2011-52    413
2 2012-01    435
3 2012-02    379

有关 的更多信息format.date,请参阅?strptime,特别是定义%U为周数的位。


编辑:

给定修改后的数据和要求,一种方法是将日期除以 7 以获得表示星期的数字。(或者更准确地说,除以一周中的秒数得到自纪元以来的周数,默认为 1970-01-01。

在代码中:

df$week <- as.Date("1970-01-01")+7*trunc(as.numeric(df$date)/(3600*24*7))
library(plyr)
ddply(df, .(week), summarize, income=sum(income))

        week income
1 2010-12-23    298
2 2010-12-30    392
3 2011-01-06    294
4 2011-01-13    152

我没有检查星期界限是否在星期日。您必须检查这一点,并在公式中插入适当的偏移量。

于 2012-07-09T13:34:26.950 回答
8

现在使用 dplyr 很简单。此外,我建议使用cut(breaks = "week")而不是format()将日期缩短为几周。

library(dplyr)
df %>% group_by(week = cut(date, "week")) %>% mutate(weekly_income = sum(income))
于 2015-07-13T19:37:37.027 回答
1

我用谷歌搜索“将工作日分组到 R 周”并遇到了这个 SO question。你提到你有多年,所以我认为我们需要跟上周数和年份,所以我在那里修改了答案format(date, format = "%U%y")

在使用中它看起来像这样:

library(plyr) #for aggregating
df <- transform(df, weeknum = format(date, format = "%y%U"))
ddply(df, "weeknum", summarize, suminc = sum(income))
#----
  weeknum suminc
1    1152    413
2    1201    435
3    1202    379

查看?strptime所有格式缩写。

于 2012-07-09T13:44:56.970 回答
1

rollapplyzoo包中尝试:

rollapply(df$income, width=7, FUN = sum, by = 7)
# [1] 487 387 443

或者,period.sumxts包中使用:

period.sum(xts(df$income, order.by=df$date), which(df$wday %in% 7))
#            [,1]
# 2011-01-01  487
# 2011-01-08  387
# 2011-01-15  443

或者,以您想要的格式获取输出:

data.frame(income = period.sum(xts(df$income, order.by=df$date), 
                               which(df$wday %in% 7)),
           week = df$week[which(df$wday %in% 7)])
#            income    week
# 2011-01-01    487 2011-00
# 2011-01-08    387 2011-01
# 2011-01-15    443 2011-02

请注意,第一周显示为2011-00因为这是在您的数据中输入的方式。您也可以使用week = df$week[which(df$wday %in% 1)]which 将匹配您的输出。

于 2012-07-09T17:01:52.800 回答
0

此解决方案受@Andrie 和@Chase 的影响。

# load plyr 
library(plyr)

# format weeks as per requirement (replace "00" with "52" and adjust corresponding year)
tmp <- list()
tmp$y <- format(df$date, format="%Y")
tmp$w <- format(df$date, format="%U")
tmp$y[tmp$w=="00"] <- as.character(as.numeric(tmp$y[tmp$w=="00"]) - 1)
tmp$w[tmp$w=="00"] <- "52"
df$week <- paste(tmp$y, tmp$w, sep = "-")

# get summary
df2 <- ddply(df, .(week), summarize, income=sum(income))

# include week ending date
tmp$week.ending <- lapply(df2$week, function(x) rev(df[df$week==x, "date"])[[1]])
df2$week.ending <- sapply(tmp$week.ending, as.character)

#      week income week.ending
# 1 2010-52    487  2011-01-01
# 2 2011-01    387  2011-01-08
# 3 2011-02    443  2011-01-15
于 2012-07-09T15:18:55.687 回答
0

df.index = df['week'] #dt变量作为索引

df.resample('W').sum() #sum 使用重采样

于 2017-01-18T06:09:15.883 回答
0

使用 dplyr:

df %>% 
  arrange(date) %>%
  mutate(week = as.numeric(date - date[1])%/%7) %>%
  group_by(week) %>%
  summarise(weekincome= sum(income))

除了 date[1],您可以使用任何日期,从您想要开始每周学习的时间开始。

于 2017-11-20T14:30:08.343 回答