2012-07-09 26 views
5

Hãy nói rằng tôi có một vài năm giá trị của dữ liệu mà trông giống như sauLàm thế nào để tập hợp con data.frame theo tuần và sau đó tổng hợp?

# 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 

Tôi muốn tổng hợp 'thu nhập' cho mỗi tuần (Chủ nhật đến thứ bẩy). Hiện tại, tôi làm như sau:

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 

Tuy nhiên tôi muốn một cách tiếp cận mạnh mẽ hơn sẽ tự động tính theo tuần. Tôi không thể tìm hiểu cách tự động đặt dữ liệu vào các tuần. Bất kì sự trợ giúp nào đều được đánh giá cao.

+0

Vui lòng không thêm giải pháp cho câu hỏi. Nếu bạn muốn trả lời câu hỏi của riêng bạn, hãy làm như vậy trong một câu trả lời (điều này được khuyến khích trên SO). – Andrie

+0

Ahh, ok, tôi không biết liệu đó có phải là hình thức xấu hay không. Tôi sẽ thêm nó như bạn đề nghị. –

Trả lời

0

Giải pháp này chịu ảnh hưởng của @Andrie và @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 
8

đầu tiên sử dụng format để chuyển đổi ngày của bạn đến các số tuần, sau đó plyr::ddply() để tính toán tóm tắt:

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 

Để biết thêm thông tin về format.date, xem ?strptime, đặc biệt là các bit định nghĩa %U như tuần con số.


EDIT:

Với dữ liệu sửa đổi và yêu cầu, một cách là để phân chia ngày 7 để có được một số số cho thấy tuần. (Hay chính xác hơn, chia cho số giây trong một tuần để có được số tuần kể từ khi kỷ nguyên, đó là 1970/01/01 theo mặc định

Trong mã:.

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 

Tôi có không kiểm tra rằng các ranh giới tuần là vào ngày Chủ nhật.Bạn sẽ phải kiểm tra điều này, và chèn một khoản bù thích hợp vào công thức

+0

Hầu như ở đó, xin vui lòng xem chỉnh sửa trong câu hỏi của tôi cho một vấn đề tôi phát hiện với phương pháp này :) –

+0

@TonyBreyal Tôi đã chỉnh sửa câu trả lời của tôi, theo yêu cầu. – Andrie

+0

cảm ơn bạn. Tôi đã đưa ra giải pháp của riêng tôi dựa trên đọc thêm về định dạng và plyr, như bạn đã đề xuất. Tôi đã thay đổi data.frame trong câu hỏi của mình để phản ánh tốt hơn những gì tôi đã làm và tôi nghĩ đó là lý do tại sao kết quả của bạn không hoàn toàn là những gì tôi đang tìm kiếm (sau khi áp dụng mã của bạn cho dữ liệu mới) nhận được giải pháp tôi cần (tôi đã thêm nó ở trên). Cảm ơn bạn rất nhiều, tôi không thể làm điều đó mà không đọc cách tiếp cận của bạn :) –

1

Tôi Googled "nhóm tuần ngày thành tuần R" và đi qua this SO question. Bạn đề cập đến bạn có nhiều năm, vì vậy tôi nghĩ chúng ta cần theo kịp cả số tuần và cả năm, vì vậy tôi đã sửa đổi các câu trả lời ở đó như vậy format(date, format = "%U%y")

Trong sử dụng nó trông như thế nà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 

Xem ?strptime cho tất cả các chữ viết tắt dạng.

+0

Hầu như ở đó, hãy xem chỉnh sửa trong câu hỏi của tôi cho một vấn đề tôi phát hiện với cách tiếp cận này :) –

+0

@TonyBreyal - trông giống như Andrie đánh tôi đến cú đấm và có một câu trả lời mạnh mẽ hơn. Ngoài ra, câu trả lời của Dwin trong câu hỏi tôi liên kết ở trên cũng nằm trong những dòng này. Chúc mừng. – Chase

+0

cảm ơn bạn đã liên kết. Tôi đã thấy nó trước đây nhưng tôi không thể tìm ra cách nó sẽ áp dụng cho yêu cầu của tôi về việc cho phép một tuần để vượt qua ranh giới năm. Bây giờ tôi có giải pháp và đánh giá cao sự giúp đỡ của bạn :) –

1

Hãy thử rollapply từ gói zoo:

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

Hoặc, sử dụng period.sum từ xts gói:

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 

Hoặc, để nhận được đầu ra ở định dạng mà bạn muốn:

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 

Lưu ý rằng tuần đầu tiên hiển thị là 2011-00 vì đó là cách nhập dữ liệu vào dữ liệu của bạn.Bạn cũng có thể sử dụng week = df$week[which(df$wday %in% 1)] phù hợp với đầu ra của bạn.

6

Điều này hiện đơn giản bằng dplyr. Ngoài ra, tôi khuyên bạn nên sử dụng cut(breaks = "week") thay vì format() để cắt các ngày thành các tuần.

library(dplyr) 
df %>% group_by(week = cut(date, "week")) %>% mutate(weekly_income = sum(income)) 
0

df.index = [ 'tuần'] df # Các biến dt như chỉ số

df.resample ('W'). Sum() #sum sử dụng resample

0

Với dplyr :

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

Thay vì ngày [1] bạn có thể có bất kỳ ngày nào khi bạn muốn bắt đầu nghiên cứu hàng tuần.

Các vấn đề liên quan