将年/周转换为日期对象

21

字符串包含'YEAR WEEK',我想使用parse_date_time()将其转换为日期对象,但是我无法使代码运行:

字符串中含有的'YEAR WEEK',我希望能够使用parse_date_time()将其转化为日期对象,但是我的代码无法正常工作:

parse_date_time(c("201510"), "YW")

我不一定要使用 lubridate,也可以使用其他包。


parse_date_time 不是 R 的基本函数。请在问题中列出您使用的任何软件包的名称。 - lmo
3
这个回答可能会对你有所帮助:http://r.789695.n4.nabble.com/Convert-201248-to-Year-Week-date-format-in-R-td4654068.html。 - Andrew Brēza
2
没错,非常感谢!我只需要添加一个星期几,as.Date(paste("201510",1),"%Y%U %u") 就可以正常工作了。 - Sebastian
2个回答

75
在将年周转换为日期之前,您必须指定一周的某一天,但更重要的是,您必须确保使用的是哪种不同的约定。 Base R 的 strptime() 函数知道一年中的 3 种定义和 2 种星期几的定义(但只支持其中 2 种输入),请参见?strptime:

年份周数

  • 美国惯例:使用星期日作为每周的第一天(通常将一月份的第一个星期日看作是第一周的第一天),作为十进制数字表示一年中的周数(00-53):%U

  • 英国惯例:使用星期一作为每周的第一天(通常将一月份的第一个星期一看作是第一周的第一天),作为十进制数字表示一年中的周数(00-53):%W

  • ISO 8601定义:根据ISO 8601标准,将一年中的周数作为十进制数字表示(01-53)。如果包含1月1日的那个星期(从星期一开始计算)中的新年有四天或更多天,则该周被认为是第1周。否则,它是上一年的最后一周,下一周是第1周:%V可以接受但在输入时会被忽略。
    请注意,还有一个基于周的年份(%G%g),应与%V一起使用,因为它可能与日历年份(%Y%y)不同。

数字星期几

  • 作为十进制数字表示的星期几(1-7,星期一是1):%u
  • 作为十进制数字表示的星期几(0-6,星期日是0):%w
  • 有趣的是,并没有格式来表示将星期日视为一周的第一天的情况。

转换具有不同约定的年-周-日

如果我们将第1天添加到字符串中并使用不同的格式,我们会得到

as.Date("2015101", "%Y%U%u")
# [1] "2015-03-09"
as.Date("2015101", "%Y%U%w")
# [1] "2015-03-09"
as.Date("2015101", "%Y%W%u")
# [1] "2015-03-09"
as.Date("2015101", "%Y%W%w")
# [1] "2015-03-09"
as.Date("2015101", "%G%V%u")
# [1] NA

对于工作日格式%u%w,我们得到相同的结果,因为在两种约定中星期一都是第一天(但处理星期日时要小心)。

对于2015年,美国和英国对于一年中的周定义是相同的,但并非所有年份都是如此,例如2001年、2007年和2018年不是:

as.Date("2018101", "%Y%U%u")
#[1] "2018-03-12"
as.Date("2018101", "%Y%W%u")
#[1] "2018-03-05"

输入中不支持 ISO 8601格式说明符。因此,我几年前创建了ISOweek:

ISOweek::ISOweek2date("2015-W10-1")
#[1] "2015-03-02"

编辑:使用星期四将一周与一个月关联

如上所述,您需要指定一周中的某个具体日期才能获得完整的日历日期。如果后续需要按月份聚合日期,则也需要指定一周中的某个工作日。

如果未指定任何工作日,并且后续需要按月份聚合日期,则可以以每周的星期四作为参考日(根据djhurio的建议)。这样可确保整个星期被分配到所属大多数工作日所在的月份。

例如,以星期日作为参考日将返回

ISOweek::ISOweek2date("2015-W09-7")
[1] "2015-03-01"

这将导致整个星期与三月份相关联,尽管一周中只有一天属于三月份,而其他六天属于二月份。以星期四作为参考日期将返回二月份的日期:

ISOweek::ISOweek2date("2015-W09-4")
[1] "2015-02-26"

2
这是一个很棒的答案。 - Canovice
非常有帮助;谢谢。 - Matt

6
是的,ISOweek包可以实现这个功能。
ISOweek::ISOweek2date(isoWeek)

但是对于另一个方向,请查看更新的lubridate包。

ISOweek::date2ISOweek(yourDate)

lubridate::isoweek(ymd(yourDate))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接