2017-04-22 5 views
1

Mit dem folgenden Code i Daten in Jahren und dieses Jahr in Wochen geteilt bekommen: an diesem AusgangSplit Termine pro Jahr und Woche und korrekte Woche Anzahl pro Jahr

library(lubridate) 

start = as.Date('2002-01-01') 
end = as.Date('2017-01-01') 

dates = sample(seq(as.Date('2002-01-01 00:00:00'), as.Date('2017-04-01 00:00:00'), by="day"), end-start,replace = FALSE) 

splitByYears = split(dates, year(dates)) 
splitYearsByWeeks = lapply(splitByYears, function(x) split(x, isoweek(x))) 

Basierend i mehrere Berechnungen getan haben. Erst als ich einige Daten wurde Plotten bemerkte ich, dass dieses Verfahren nicht perfekt funktioniert:

>splitYearsByWeeks 
... 

$`2011`$`52` 
[1] "2011-01-01" "2011-01-02" "2011-12-26" 


$`2012` 
$`2012`$`1` 
[1] "2012-12-31" "2012-01-02" "2012-01-06" "2012-01-08" 

... 

Hier 2011-01-01 und 2011-01-02 ein Teil der 52th Woche des Jahres 2010, aber wegen der Spaltung zuerst nach Jahr werden die Daten der 52. Woche von 2011 zugeordnet. Das gleiche Problem tritt in 2012-12-31 auf, dieses Datum ist Teil der ersten Woche von 2013, wird aber der ersten Woche von 2012 zugewiesen, weil ich die Funktion auf jedes Jahr getrennt anwende.

Aufteilen nach Jahr und dann aufteilen jedes Jahr in Wochen geben mir das Format, das ich brauche, aber die Woche-Jahr-Beziehung kann nicht korrekt sein. Um die richtige Wochennummer erhalten kann ich geteilt zuerst von Woche und als nach Jahren:

splitByWeek = split(dates, isoweek(dates)) 
splitWeeksByYear = lapply(splitByWeek, function(x) split(x, year(x))) 

Aber das Format ist nicht das, was ich brauche:

>splitWeeksByYear 
... 
$`53` 
$`53`$`2004` 
[1] "2004-12-31" "2004-12-29" "2004-12-28" 

$`53`$`2005` 
[1] "2005-01-01" 

$`53`$`2009` 
[1] "2009-12-28" 

$`53`$`2015` 
[1] "2015-12-30" 

$`53`$`2016` 
[1] "2016-01-03" 

Was ist der beste Weg, um die richtigen Wochen im Format ich brauche: Liste von $ Jahr $ WocheNum? (vielleicht das zweite Ergebnis umwandeln oder ganz anders machen?)

+0

'Format (Termine , "% Y-% U") '? –

Antwort

0

Die Wochennummerierung nach ISO 8601 hat den Vorteil, dass ISO-Wochen immer aus 7 Tagen ohne Überlappung oder Lücke bestehen (im Gegensatz zu den USA und UK) Wochennummernkonventionen).

Es kann jedoch vorkommen, dass ein paar Tage rund um Neujahr zu einer ISO-Woche mit einem anderen ISO-Kalenderjahr als dem Kalenderjahr gehören.

Aus diesem Grund lubridate eine isoyear() hat und eine isoweek() Funktion und format() erkennt das Format-Spezifizierer %G, %g (ISO Woche basierte Jahr) und %V (ISO Woche).

Also, mit einer geringfügigen Änderung Code des OP funktioniert wie erwartet:

library(lubridate) 
splitByYears = split(dates, isoyear(dates)) 
splitYearsByWeeks = lapply(splitByYears, function(x) split(x, isoweek(x))) 
splitYearsByWeeks$`2011`$`52` 
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30" 
[7] "2011-12-26" 
splitYearsByWeeks$`2012`$`1` 
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05" 
[7] "2012-01-02" 

jedoch dates von der ISO Woche basierte Aufspaltung Jahr und ISO Woche kann b e erreicht in drei leicht unterschiedliche Weise in einem Rutsch auch:

splitted <- split(dates, format(dates, "%G-W%V")) 
splitted$`2011-W52` 
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30" 
[7] "2011-12-26" 
splitted$`2012-W01` 
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05" 
[7] "2012-01-02" 

Alternativ können Sie die ISOweek package von denen ich der Autor bin verwenden:

splitted <- split(dates, ISOweek::ISOweek(dates)) 

Die split() Funktion akzeptiert auch eine Liste von Faktoren, wobei deren Interaktion für die Gruppierung verwendet wird:

library(lubridate) 
splitted <- split(dates, list(isoyear(dates), isoweek(dates))) 
splitted$`2011.52` 
[1] "2011-12-28" "2011-12-27" "2011-12-29" "2011-12-31" "2012-01-01" "2011-12-30" 
[7] "2011-12-26" 
splitted$`2012.1` 
[1] "2012-01-03" "2012-01-07" "2012-01-06" "2012-01-04" "2012-01-08" "2012-01-05" 
[7] "2012-01-02" 
Verwandte Themen