2012-07-09 7 views
5

はのは私が毎週(土スルー日曜日)のための「収入」を合計したいと思い、次のdata.frameをサブセット化して合計する方法は?

# 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 

ようになり、データの価値は数年を持っているとしましょう。現在、私は次のことを行っています:

しかし、私は週によって自動的に合計されるより堅牢なアプローチを希望します。データを自動的にサブセットに数週間に分割する方法はありません。どんな助けでも大歓迎です。

+0

質問に解決策を追加しないでください。あなた自身の質問に答えるためには、答えに記入してください(これはSOで奨励されています)。 – Andrie

+0

ああ、それは悪い形になるかどうかわかりませんでした。あなたの提案通りに私はそれを追加します。 –

答えて

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 
8

要約を計算するために、その後の週番号にあなたの日付を変換するためにまず使用formatplyr::ddply()format.dateの詳細については

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 

を、?strptimeを参照してください、特定の週として%U定義ビットに数。


EDIT:

が変更されたデータと要件を考えると、一つの方法は、週を示す数値番号を取得するために7日を分割することです。 (より正確には、一週間の秒数で割るには、デフォルトでは1970年1月1日であるエポック、以来、週数を取得するためのコードで

:。

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 

私が持っています

+0

ほとんどのところ、このアプローチで私が見つけた問題について私の質問に編集を見てください:) –

+0

@TonyBreyal私は要求通りに私の答えを編集しました。 – Andrie

+0

ありがとうございます。私はあなたが示唆したように、フォーマットとプライヤーのさらなる読書を基にした私自身の解決策を思いついた。私は私の質問でdata.frameを変更して、私が後にしたことをよりよく反映させました。あなたの結果が(私のコードを新しいデータに適用した後に)探していたものではないと思います。私が必要とした解決策を得る(私はそれを上に加えた)。ありがとう、私はあなたのアプローチを読むことなくそれをしなかった:) –

1

私はグーグルで週休日をRにして、this 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を参照してください。

+0

ほぼそこに、私はこのアプローチで発見した問題の私の質問に編集を参照してください:) –

+0

@トニーブレイダル - アンドリューのように見えるパンチより堅牢な答えを持っています。また、私が上にリンクした質問のDwinの答えは、これらの線に沿っています。乾杯。 – Chase

+0

ご連絡ありがとうございました。これまで私はそれを見ていましたが、年の境界を越える1週間を許可するという私の要求にどのように適用されるのかは分かりませんでした。私は今解決して、あなたの助けに感謝:) –

1

zooパッケージからrollapplyをお試しください:

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

または、xtsパッケージからperiod.sumを使用します。

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)]を使用することもできます。

6

これはdplyrを使用すると簡単になりました。また、format()ではなく、cut(breaks = "week")を使用して、日付を数週間に短縮することをお勧めします。 DFの[ '週'] dplyrで指標としてDT変数

df.resample( 'W')。和()#sum用いてリサンプル

0

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

日付[1]の代わりに、週単位のスタディを開始する日付を指定できます。

0

を#このdf.index =

library(dplyr) 
df %>% group_by(week = cut(date, "week")) %>% mutate(weekly_income = sum(income)) 
関連する問題