2013-03-07 22 views
14

Ho un set di dati con posizioni e date. Vorrei calcolare la settimana dell'anno come numero (00-53) ma usando giovedì come primo giorno della settimana. I dati si presenta così:Calcolare il numero della settimana (0-53) nell'anno

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 

So che c'è strftime funzione per il calcolo settimana dell'anno ma è solo possibile utilizzare Lunedi o Domenica come il primo giorno della settimana. Qualsiasi aiuto sarebbe molto apprezzato.

+0

Perché vorresti farlo, se posso chiedere? – Arun

+3

Quindi se un anno è iniziato il martedì, la settimana 1 è Mar/Mer e la settimana 2 inizia giovedì ...? – joran

+0

si. La settimana dovrebbe essere da martedì fino a mercoledì incluso. – Eco06

risposta

22

Basta aggiungere 4 ai valori-data formattata:

> 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 

Questo utilizza una convenzione di conteggio basato 0 dato che questo è ciò che strftime offre e siamo solo piggybacking fuori che base di codice, in modo che il primo Venerdì in un l'anno che inizia martedì, come nel 2013, sarebbe stato un risultato di 1 settimana. Aggiungi 1 al valore se desideri una convenzione basata su 1. (Fondamentalmente, i valori basati sulla data sono in una sequenza intera da "origine" in modo che non riconoscono realmente anni o settimane. L'aggiunta di 4 sposta semplicemente il fotogramma di riferimento dell'intero in Date.)

Modifica nota. Modificato su tre strategie aggiuntive per consiglio di Gabor. .... che ancora non affronta la questione di come affrontare l'ultima settimana dell'anno precedente.

+1

C'è qualche domanda su quale sia la definizione del numero della settimana, ma a qualsiasi tasso ci sono 1, 4, 5, 6, 7, 9 giovedì nell'anno prima delle 6 date nella domanda, rispettivamente, che solleva una questione se l'8 nella risposta è corretta. Anche 'format (as.Date (" 2013-12-31 ") + 4,"% U ")' dà 00. –

+0

La strategia "add-4" crea un incremento il giovedì, quindi il conteggio dei giovedì sarebbe concordato con una strategia "add-3". –

+0

Una correzione per il problema di fine anno potrebbe essere quella di sottrarre 7 giorni se è in dicembre e quindi aggiungere 1 al conteggio settimana: 'ifelse (months (d) ==" December ", \t as.numeric (formato (d-4, "% U")) + 1, \t as.numeric (formato (d + 3, "% U"))) ' –

2

Poiché la domanda ha stabilito che la settimana va da 00 a 53, assumiamo che il numero della settimana sia il numero di giovedì dell'anno precedente o precedente alla data in questione. Pertanto, il primo giovedì dell'anno inizia la settimana 1 e la settimana 0 viene assegnata a tutti i giorni precedenti.

(Ci sono stati commenti che se il primo giorno dell'anno fosse martedì, allora sarebbe la settimana 1, ma se così fosse non ci potrebbe mai essere una settimana 0 come sembra essere richiesto nell'argomento quindi qualche chiarimento su può essere richiesta la definizione del numero della settimana, qui utilizzeremo la definizione nel paragrafo precedente, ma non sarebbe difficile cambiarla se sapessimo quale fosse la definizione, ad esempio, se avessimo sempre desiderato la prima settimana nell'anno per essere 1 anche se fosse una settimana breve, potremmo aggiungere !is.thu(jan1(d)) al risultato.)

Entrambe le soluzioni di seguito sono abbastanza brevi da poter essere espresse in una dichiarazione; tuttavia, li abbiamo suddivisi in diverse brevi funzioni ciascuna per chiarezza. Il primo è particolarmente semplice, ma il secondo è automaticamente vettorizzato senza la necessità di un sapply e probabilmente sarebbe più efficiente.

1. somma giovedì nell'anno Questa soluzione presuppone l'ingresso d è di classe "Date" e solo riassume il numero di giovedì durante l'anno prima o su di esso:

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")))) 
} 

possiamo testare in questo modo :

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. nextthu

In base alla funzione nextfri nello zoo quickref vignette, vediamo che il numero di giorni da Epoch (1970-01-01) del giovedì successivo (o il giorno in questione se è già un giovedì) è dato da nextthu nel primo linea sotto.Applicando questo per il primo giorno dell'anno si ricava il risultato in cui d è come prima:

nextthu <- function(d) 7 * ceiling(as.numeric(d)/7) 

week4a <- function(d) (as.numeric(d) - nextthu(jan1(d))) %/% 7 + 1 

e qui è una prova

week4a(d) # 1 4 5 6 7 9 

aggiunto: Corretto il bug nella seconda soluzione.