R:如何获取月份的周数
我是R的新手。R:如何获取月份的周数,r,date,R,Date,我是R的新手。 我想知道日期所属的月份的周数 通过使用以下代码: >CurrentDate<-Sys.Date() >Week Number <- format(CurrentDate, format="%U") >Week Number "31" >当前日期周数周数 "31" %U将返回一年中的周数。 但是我想要一个月的周数。 如果日期是2014-08-01,那么我想得到1。(该日期属于该月的第一周) 例如: 2014-09-04->1(该日期属于该月的第一周
我想知道日期所属的月份的周数 通过使用以下代码:
>CurrentDate<-Sys.Date()
>Week Number <- format(CurrentDate, format="%U")
>Week Number
"31"
>当前日期周数周数
"31"
%U将返回一年中的周数。但是我想要一个月的周数。
如果日期是2014-08-01,那么我想得到1。(该日期属于该月的第一周) 例如:
2014-09-04->1(该日期属于该月的第一周)。
2014-09-10->2(该日期属于该月的第二周)。
等等 我怎么能得到这个 参考:
我不知道R,但如果你取当月第一天的一周,你可以用它来获得当月的一周
2014-09-18
First day of month = 2014-09-01
Week of first day on month = 36
Week of 2014-09-18 = 38
Week in the month = 1 + (38 - 36) = 3
您可以使用lubridate软件包中的
day
。我不确定包中是否有一周的月份类型函数,但我们可以进行计算
library(lubridate)
curr <- Sys.Date()
# [1] "2014-08-08"
day(curr) ## 8th day of the current month
# [1] 8
day(curr) / 7 ## Technically, it's the 1.14th week
# [1] 1.142857
ceiling(day(curr) / 7) ## but ceiling() will take it up to the 2nd week.
# [1] 2
库(lubridate)
curr类似于工作日
函数:
monthweeks <- function(x) {
UseMethod("monthweeks")
}
monthweeks.Date <- function(x) {
ceiling(as.numeric(format(x, "%d")) / 7)
}
monthweeks.POSIXlt <- function(x) {
ceiling(as.numeric(format(x, "%d")) / 7)
}
monthweeks.character <- function(x) {
ceiling(as.numeric(format(as.Date(x), "%d")) / 7)
}
dates <- sample(seq(as.Date("2000-01-01"), as.Date("2015-01-01"), "days"), 7)
dates
#> [1] "2004-09-24" "2002-11-21" "2011-08-13" "2008-09-23" "2000-08-10" "2007-09-10" "2013-04-16"
monthweeks(dates)
#> [1] 4 3 2 4 2 2 3
我遇到了同样的问题,我用data.table
package中的mday
解决了这个问题。此外,我意识到在使用天花()
函数时,还需要考虑“第五周”的情况。例如,每月30天的上限上限(30/7)
将给出5!因此,下面的ifelse
语句
# Create a sample data table with days from year 0 until present
DT <- data.table(days = seq(as.Date("0-01-01"), Sys.Date(), "days"))
# compute the week of the month and account for the '5th week' case
DT[, week := ifelse( ceiling(mday(days)/7)==5, 4, ceiling(mday(days)/7) )]
> DT
days week
1: 0000-01-01 1
2: 0000-01-02 1
3: 0000-01-03 1
4: 0000-01-04 1
5: 0000-01-05 1
---
736617: 2016-10-14 2
736618: 2016-10-15 3
736619: 2016-10-16 3
736620: 2016-10-17 3
736621: 2016-10-18 3
计算超过70万天的周数大约需要3秒钟
但是,上面的上限
方式始终会使最后一周比所有其他周都长(四周有7天、7天、7天和9天或10天)。另一种方法是使用
ceiling(1:31/31*4)
[1] 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4
在31天的月内,每周分别有7天、8天、8天和8天
DT[, week2 := ceiling(mday(days)/31*4)]
使用lubridate
可以
ceiling((day(date) + first_day_of_month_wday(date) - 1) / 7)
其中函数month的first\u day\u wday
返回每月第一天的工作日
first_day_of_month_wday <- function(dx) {
day(dx) <- 1
wday(dx)
}
first_day_of u month_wday我不知道任何内置函数,但需要一个解决方法
CurrentDate <- Sys.Date()
# The number of the week relative to the year
weeknum <- as.integer( format(CurrentDate, format="%U") )
# Find the minimum week of the month relative to the year
mindatemonth <- as.Date( paste0(format(CurrentDate, "%Y-%m"), "-01") )
weeknummin <- as.integer( format(mindatemonth, format="%U") ) # the number of the week of the first week within the month
# Calculate the number of the week relative to the month
weeknum <- weeknum - (weeknummin - 1) # this is as an integer
# With the following you can convert the integer to the same format of
# format(CurrentDate, format="%U")
formatC(weeknum, width = 2, flag = "0")
CurrentDate使用lubridate
软件包有一种简单的方法:
stringi::stri_datetime_fields(dates)$WeekOfMonth
#> [1] 4 4 2 4 2 3 3
isoweek()
返回ISO 8601系统中显示的一周,该系统使用重复出现的闰周
epiweek()
是美国疾病预防控制中心版的流行病学周。它遵循的规则与
isoweek()
但从周日开始。在世界其他地区,该公约将在周一开始流行病学周,这与isoweek()
相同
参考问题概述
很难判断哪些答案有效,因此我在第n周构建了自己的函数,并与其他函数进行了对比测试
导致大多数答案不正确的问题是:
- 一个月的第一周通常是很短的一周
- 与本月最后一周相同
例如,2019年10月1日是周二,因此10月6日(即周日)已经是第二周。此外,连续月份通常在各自的计数中共享同一周,这意味着上个月的最后一周通常也是当前月份的第一周。因此,我们预计每年的周数将超过52周,有些月份的跨度为6周。
结果比较
下面的表格显示了上述建议算法出现错误的示例:
DATE Tori user206 Scri Klev Stringi Grot Frei Vale epi iso coni
Fri-2016-01-01 1 1 1 1 5 1 1 1 1 1 1
Sat-2016-01-02 1 1 1 1 1 1 1 1 1 1 1
Sun-2016-01-03 2 1 1 1 1 2 2 1 -50 1 2
Mon-2016-01-04 2 1 1 1 2 2 2 1 -50 -51 2
----
Sat-2018-12-29 5 5 5 5 5 5 5 4 5 5 5
Sun-2018-12-30 6 5 5 5 5 6 6 4 -46 5 6
Mon-2018-12-31 6 5 5 5 6 6 6 4 -46 -46 6
Tue-2019-01-01 1 1 1 1 6 1 1 1 1 1 1
您可以看到,由于对部分周周期的治疗,只有Grothendieck、conighion、Freitas和Tori是正确的。我比较了从100年到3000年的所有日子;这四个国家之间没有区别。(Stringi将周末记为单独的递增时段可能是正确的,但我没有进行确认;epiweek()和isoweek()由于它们的预期用途,在使用它们进行周末递增时,在接近年终时表现出一些奇怪的行为。)
速度比较
以下是Tori、Grothendieck、Conighion和Freitas实现之间的效率测试
希望这项工作能节省人们的时间,省去他们筛选所有答案的时间。我参加聚会迟到了,也许没人会读到这个答案
无论如何,为什么不保持简单,这样做:
library(lubridate)
x <- ymd(20200311, 20200308)
week(x) - week(floor_date(x, unit = "months")) + 1
[1] 3 2
库(lubridate)
x只需这样做:
库(lubridate)
ds1$Week星期天属于哪一周?(也就是说,在你想要结果的地方,哪一天是一周的第一天?@JoachimIsaksson Sunday是我工作日的第一天这项工作这周可以用R写成这样:d@G.Grothendieck这是唯一适用于“2014-08-21”的答案,条件是“2014-08-01”是8月1日和“2014-08-04”是第二周。如果你回答的话,我会在perlice的基础上再加上你一个。不要用这种方法。它不起作用,因为它没有考虑月的第一天的工作日。例如,2017年9月1日是星期五。对9月4日星期一使用此方法,我们得到的上限(天(ymd(“20170904”))/7)
等于1
,但应该是该月的第二周。请注意,这从周一开始计算周数。如果一个月的第二天是星期一,这将是第二周。你好,谢谢。这对我很有用。它简单有效。我只是不明白+1是什么。我相信lubridate
中的week
将返回从日期到1月1日之间完成的7天周期数(加1)。OP请求是一个月的周数(不是从年初开始)。实际上,我的答案是检索年度周数。如果有人在寻找一种快速提取年度周数的方法时,而不是从月份(如我所做的)发现了这篇文章,也许我可以把它作为额外的信息。
# prep
library(lubridate)
library(tictoc)
kepler<- ymd(15711227) # Kepler's birthday since it's a nice day and gives a long vector of dates
some_dates<- seq(kepler, today(), by='day')
# test speed of Tori algorithm
tic(msg = 'Tori')
Tori<- (5 + day(some_dates) + wday(floor_date(some_dates, 'month'))) %/% 7
toc()
Tori: 0.19 sec elapsed
# test speed of Grothendieck algorithm
wk <- function(x) as.numeric(format(x, "%U"))
tic(msg = 'Grothendieck')
Grothendieck<- (wk(some_dates) - wk(as.Date(cut(some_dates, "month"))) + 1)
toc()
Grothendieck: 1.99 sec elapsed
# test speed of conighion algorithm
tic(msg = 'conighion')
weeknum <- as.integer( format(some_dates, format="%U") )
mindatemonth <- as.Date( paste0(format(some_dates, "%Y-%m"), "-01") )
weeknummin <- as.integer( format(mindatemonth, format="%U") ) # the number of the week of the first week within the month
conighion <- weeknum - (weeknummin - 1) # this is as an integer
toc()
conighion: 2.42 sec elapsed
# test speed of Freitas algorithm
first_day_of_month_wday <- function(dx) {
day(dx) <- 1
wday(dx)
}
tic(msg = 'Freitas')
Freitas<- ceiling((day(some_dates) + first_day_of_month_wday(some_dates) - 1) / 7)
toc()
Freitas: 0.97 sec elapsed
# some_dates above is any vector of dates, like:
some_dates<- seq(ymd(20190101), today(), 'day')
nth_week<- function(dates = NULL,
count_weeks_in = c("month","year"),
begin_week_on = "Sunday"){
require(lubridate)
count_weeks_in<- tolower(count_weeks_in[1])
# day_names and day_index are for beginning the week on a day other than Sunday
# (this vector ordering matters, so careful about changing it)
day_names<- c("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday")
# index integer of first match
day_index<- pmatch(tolower(begin_week_on),
tolower(day_names))[1]
### Calculate week index of each day
if (!is.na(pmatch(count_weeks_in, "year"))) {
# For year:
# sum the day of year, index for day of week at start of year, and constant 5
# then integer divide quantity by 7
# (explicit on package so lubridate and data.table don't fight)
n_week<- (5 +
lubridate::yday(dates) +
lubridate::wday(floor_date(dates, 'year'),
week_start = day_index)
) %/% 7
} else {
# For month:
# same algorithm as above, but for month rather than year
n_week<- (5 +
lubridate::day(dates) +
lubridate::wday(floor_date(dates, 'month'),
week_start = day_index)
) %/% 7
}
# naming very helpful for review
names(n_week)<- paste0(lubridate::wday(dates,T), '-', dates)
n_week
}
# Example raw vector output:
some_dates<- seq(ymd(20190930), today(), by='day')
nth_week(some_dates)
Mon-2019-09-30 Tue-2019-10-01 Wed-2019-10-02
5 1 1
Thu-2019-10-03 Fri-2019-10-04 Sat-2019-10-05
1 1 1
Sun-2019-10-06 Mon-2019-10-07 Tue-2019-10-08
2 2 2
Wed-2019-10-09 Thu-2019-10-10 Fri-2019-10-11
2 2 2
Sat-2019-10-12 Sun-2019-10-13
2 3
# Example tabled output:
library(tidyverse)
nth_week(some_dates) %>%
enframe('DATE','nth_week_default') %>%
cbind(some_year_day_options = as.vector(nth_week(some_dates, count_weeks_in = 'year', begin_week_on = 'Mon')))
DATE nth_week_default some_year_day_options
1 Mon-2019-09-30 5 40
2 Tue-2019-10-01 1 40
3 Wed-2019-10-02 1 40
4 Thu-2019-10-03 1 40
5 Fri-2019-10-04 1 40
6 Sat-2019-10-05 1 40
7 Sun-2019-10-06 2 40
8 Mon-2019-10-07 2 41
9 Tue-2019-10-08 2 41
10 Wed-2019-10-09 2 41
11 Thu-2019-10-10 2 41
12 Fri-2019-10-11 2 41
13 Sat-2019-10-12 2 41
14 Sun-2019-10-13 3 41
library(lubridate)
x <- ymd(20200311, 20200308)
week(x) - week(floor_date(x, unit = "months")) + 1
[1] 3 2