14

我有一个包含位置和日期的数据集。我想将一年中的星期计算为数字(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 函数用于计算一年中的一周,但只能使用星期一或星期日作为一周的第一天。任何帮助将不胜感激。

4

2 回答 2

22

只需将 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 的建议更改为添加三个策略。....这仍然没有解决如何处理前一年最后一周的问题。

于 2013-03-07T17:59:14.833 回答
2

由于问题表明周从 00 到 53,我们假设周数是相关日期或之前一年中的星期四数。因此,一年中的第一个星期四从第 1 周开始,第 0 周被分配到之前的任何日子。

(有人评论说,如果一年中的第一天是星期二,那将是第 1 周,但如果是这种情况,则永远不可能有第 0 周,这似乎是该主题所要求的,因此请澄清一下week number 可能是必需的。这里我们将使用上一段中的定义,但是如果我们知道定义是什么就不会很难改变它。例如,如果我们总是希望一年中的第一周是 1,即使是很短的一周,我们也可以添加!is.thu(jan1(d))到结果中。)

以下两种解决方案都足够短,可以用一个语句来表达;但是,为了清楚起见,我们将它们分解为几个简短的函数。第一个特别简单,但第二个是自动矢量化的,不需要 asapply并且可能更有效。

1. sum Thursdays in year 这个解决方案假设输入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.下周四

根据zoo quickref vignettenextfri中的函数,我们看到自下一个星期四(或相关日期,如果它已经是星期四)的 Epoch (1970-01-01) 以来的天数如第一行所示以下。将此应用于一年的第一天,我们得出的结果与以前一样:nextthud

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

添加:修复了第二个解决方案中的错误。

于 2013-03-07T19:33:38.807 回答