qué - que numero de semana estamos 2018
¿Cómo obtener números de semana a partir de fechas? (7)
Creo que el problema es que el cálculo de la week
alguna manera usa el primer día del año. No entiendo la mecánica interna, pero puedes ver a qué me refiero con este ejemplo:
library(data.table)
dd <- seq(as.IDate("2013-12-20"), as.IDate("2014-01-20"), 1)
# dd <- seq(as.IDate("2013-12-01"), as.IDate("2014-03-31"), 1)
dt <- data.table(i = 1:length(dd),
day = dd,
weekday = weekdays(dd),
day_rounded = round(dd, "weeks"))
## Now let''s add the weekdays for the "rounded" date
dt[ , weekday_rounded := weekdays(day_rounded)]
## This seems to make internal sense with the "week" calculation
dt[ , weeknumber := week(day)]
dt
i day weekday day_rounded weekday_rounded weeknumber
1: 1 2013-12-20 Friday 2013-12-17 Tuesday 51
2: 2 2013-12-21 Saturday 2013-12-17 Tuesday 51
3: 3 2013-12-22 Sunday 2013-12-17 Tuesday 51
4: 4 2013-12-23 Monday 2013-12-24 Tuesday 52
5: 5 2013-12-24 Tuesday 2013-12-24 Tuesday 52
6: 6 2013-12-25 Wednesday 2013-12-24 Tuesday 52
7: 7 2013-12-26 Thursday 2013-12-24 Tuesday 52
8: 8 2013-12-27 Friday 2013-12-24 Tuesday 52
9: 9 2013-12-28 Saturday 2013-12-24 Tuesday 52
10: 10 2013-12-29 Sunday 2013-12-24 Tuesday 52
11: 11 2013-12-30 Monday 2013-12-31 Tuesday 53
12: 12 2013-12-31 Tuesday 2013-12-31 Tuesday 53
13: 13 2014-01-01 Wednesday 2014-01-01 Wednesday 1
14: 14 2014-01-02 Thursday 2014-01-01 Wednesday 1
15: 15 2014-01-03 Friday 2014-01-01 Wednesday 1
16: 16 2014-01-04 Saturday 2014-01-01 Wednesday 1
17: 17 2014-01-05 Sunday 2014-01-01 Wednesday 1
18: 18 2014-01-06 Monday 2014-01-01 Wednesday 1
19: 19 2014-01-07 Tuesday 2014-01-08 Wednesday 2
20: 20 2014-01-08 Wednesday 2014-01-08 Wednesday 2
21: 21 2014-01-09 Thursday 2014-01-08 Wednesday 2
22: 22 2014-01-10 Friday 2014-01-08 Wednesday 2
23: 23 2014-01-11 Saturday 2014-01-08 Wednesday 2
24: 24 2014-01-12 Sunday 2014-01-08 Wednesday 2
25: 25 2014-01-13 Monday 2014-01-08 Wednesday 2
26: 26 2014-01-14 Tuesday 2014-01-15 Wednesday 3
27: 27 2014-01-15 Wednesday 2014-01-15 Wednesday 3
28: 28 2014-01-16 Thursday 2014-01-15 Wednesday 3
29: 29 2014-01-17 Friday 2014-01-15 Wednesday 3
30: 30 2014-01-18 Saturday 2014-01-15 Wednesday 3
31: 31 2014-01-19 Sunday 2014-01-15 Wednesday 3
32: 32 2014-01-20 Monday 2014-01-15 Wednesday 3
i day weekday day_rounded weekday_rounded weeknumber
Mi solución es esta función: https://github.com/geneorama/geneorama/blob/master/R/round_weeks.R
round_weeks <- function(x){
require(data.table)
dt <- data.table(i = 1:length(x),
day = x,
weekday = weekdays(x))
offset <- data.table(weekday = c(''Sunday'', ''Monday'', ''Tuesday'', ''Wednesday'',
''Thursday'', ''Friday'', ''Saturday''),
offset = -(0:6))
dt <- merge(dt, offset, by="weekday")
dt[ , day_adj := day + offset]
setkey(dt, i)
return(dt[ , day_adj])
}
Por supuesto, puede cambiar fácilmente la compensación para hacer el lunes primero o lo que sea. La mejor manera de hacer esto sería agregar un desplazamiento al desplazamiento ... pero todavía no lo he hecho.
Proporcioné un enlace a mi paquete geneorama simple, pero no confíe demasiado en él porque es probable que cambie y no esté muy documentado.
Buscando una función en R para convertir fechas en números de semana (del año), fui por week
desde el paquete data.table
. Sin embargo, observé algún comportamiento extraño:
> week("2014-03-16") # Sun, expecting 11
[1] 11
> week("2014-03-17") # Mon, expecting 12
[1] 11
> week("2014-03-18") # Tue, expecting 12
[1] 12
¿Por qué el número de la semana está cambiando a 12 el martes, en lugar del lunes? ¿Qué me estoy perdiendo? (¿La zona horaria debería ser irrelevante ya que solo hay fechas ?!)
También se aprecian otras sugerencias para las funciones R (base).
En realidad, creo que puede haber descubierto un error en la función de la week(...)
, o al menos un error en la documentación. Con suerte, alguien intervendrá y explicará por qué me equivoco.
Mirando el código:
library(lubridate)
> week
function (x)
yday(x)%/%7 + 1
<environment: namespace:lubridate>
La documentación establece:
Semanas es el número de períodos completos de siete días que han ocurrido entre la fecha y el 1 de enero, más uno.
Pero como el 1 de enero es el primer día del año (no el cero), la primera "semana" será un período de seis días. El código debe ser (??)
(yday(x)-1)%/%7 + 1
NB: está utilizando la week(...)
en el paquete data.table
, que es el mismo código que lubridate::week
excepto que obliga a todo a ser entero en lugar de numérico para la eficiencia. Entonces esta función tiene el mismo problema (??).
Entiendo la necesidad de paquetes en ciertas situaciones, pero el lenguaje base es tan elegante y tan probado (y depurado y optimizado).
Por qué no:
dt <- as.Date("2014-03-16")
dt2 <- as.POSIXlt(dt)
dt2$yday
[1] 74
Y luego su elección si la primera semana del año es cero (como en la indexación en C) o 1 (como en la indexación en R).
No hay paquetes para aprender, actualizar, preocuparse por errores en.
Si desea obtener el número de la semana con el año, use: "%YW%V"
:
e.g yearAndweeks <- strftime(dates, format = "%Y-W%V")
asi que
> strftime(c("2014-03-16", "2014-03-17","2014-03-18", "2014-01-01"), format = "%Y-W%V")
se convierte en:
[1] "2014-W11" "2014-W12" "2014-W12" "2014-W01
"
Si lo intentas con lubricante:
library(lubridate)
lubridate::week(ymd("2014-03-16", "2014-03-17","2014-03-18", ''2014-01-01''))
[1] 11 11 12 1
El patrón es el mismo. Prueba isoweek
lubridate::isoweek(ymd("2014-03-16", "2014-03-17","2014-03-18", ''2014-01-01''))
[1] 11 12 12 1
Usando solo la base, escribí la siguiente función.
Nota:
- Asume que Mon es el día número 1 en la semana
- La primera semana es la semana 1
- Devuelve 0 si la semana es 52 del año pasado
Afinar para adaptarse a sus necesidades.
findWeekNo <- function(myDate){
# Find out the start day of week 1; that is the date of first Mon in the year
weekday <- switch(weekdays(as.Date(paste(format(as.Date(myDate),"%Y"),"01-01", sep = "-"))),
"Monday"={1},
"Tuesday"={2},
"Wednesday"={3},
"Thursday"={4},
"Friday"={5},
"Saturday"={6},
"Sunday"={7}
)
firstMon <- ifelse(weekday==1,1, 9 - weekday )
weekNo <- floor((as.POSIXlt(myDate)$yday - (firstMon-1))/7)+1
return(weekNo)
}
findWeekNo("2017-01-15") # 2
Paquete base
Usando la función strftime
pasando el argumento %V
para obtener la semana del año como número decimal (01–53) como se define en ISO 8601. (Más detalles en el documento:? Strftime)
strftime(c("2014-03-16", "2014-03-17","2014-03-18", "2014-01-01"), format = "%V")
Salida:
[1] "11" "12" "12" "01"