web-dev-qa-db-ja.com

年の週番号(0-53)を計算します

場所と日付を含むデータセットがあります。週を数値(00〜53)として計算したいのですが、木曜日を週の最初の日として使用します。データは次のようになります。

  location <- c(a,b,a,b,a,b)
  date <- c("04-01-2013","26-01-2013","03-02-2013","09-02-2013","20-02-2013","03-03-2013")
  mydf <- data.frame(location, date)
  mydf

週を計算するためのstrftime関数があることは知っていますが、週の最初の日として使用できるのは月曜日または日曜日のみです。どんな助けでも大歓迎です。

14
Eco06

日付形式の値に4を追加するだけです。

> mydf$Dt <- as.Date(mydf$date, format="%d-%m-%Y")
> weeknum <- as.numeric( format(mydf$Dt+3, "%U"))
> weeknum
[1] 1 4 5 6 7 9

これは0ベースのカウント規則を使用します。これはstrftimeが提供するものであり、コードベースを便乗しているだけなので、2013年の場合のように火曜日に始まる年の最初の金曜日は1週間の結果になります。 1ベースの規則が必要な場合は、値に1を追加します。 (基本的に、日付形式の値は「原点」から整数シーケンスであるため、実際には年または週を認識しません。4を追加すると、基になる日付整数の参照フレームがシフトするだけです。)

メモを編集します。 Gaborのアドバイスに従って3つの戦略を追加するように変更されました。 ....これはまだ前年の最後の週にどう対処するかという問題に対処していません。

22
42-

質問には週が00から53になると記載されているため、週番号は問題の日付以前の年の木曜日の数であると想定します。したがって、その年の最初の木曜日は第1週から始まり、第0週はそれより前の任意の日に割り当てられます。

(年の最初の日が火曜日の場合、それは第1週になるというコメントがありましたが、その場合、主題で必要とされるように第0週はあり得ないので、正確に何の定義が何であるかについてのいくつかの明確化週番号が必要な場合があります。ここでは前の段落の定義を使用しますが、定義が何であるかを知っていれば変更するのは難しくありません。たとえば、年の最初の週が常に必要な場合は、短い週であっても1になると、結果に!is.thu(jan1(d))を追加できます。)

以下の両方のソリューションは、1つのステートメントで表現できるほど十分に短いものです。ただし、わかりやすくするために、それぞれをいくつかの短い関数に分解しました。前者は特に単純ですが、後者はsapplyを必要とせずに自動的にベクトル化され、より効率的になる可能性があります。

1。年の木曜日の合計このソリューションは、入力dがクラス"Date"であると想定し、その前またはその年の木曜日の数を合計するだけです。

is.thu <- function(x) weekdays(x) == "Thursday"
jan1 <- function(x) as.Date(cut(x, "year"))

week4 <- function(d) {
  sapply(d, function(d) sum(is.thu(seq(jan1(d), d, by = "day"))))
}

次のようにテストできます。

d <- as.Date(c("2013-01-04", "2013-01-26", "2013-02-03", "2013-02-09", 
    "2013-02-20", "2013-03-03"))
week4(d) # 1 4 5 6 7 9

2。 nextthu

Zoo quickref vignettenextfri関数に基づいて、次の木曜日のエポック(1970-01-01)からの日数(または問題の日すでに木曜日)は、以下の最初の行のnextthuで指定されたとおりです。これを年の最初の日に適用すると、dが以前と同じになる結果が得られます。

nextthu <- function(d) 7 * ceiling(as.numeric(d) / 7)

week4a <- function(d) (as.numeric(d) - nextthu(jan1(d))) %/% 7 + 1

そしてここにテストがあります

week4a(d) # 1 4 5 6 7 9

追加:2番目のソリューションのバグを修正しました。

2
G. Grothendieck