2012-10-30 8 views
5

Pracuję z dataframe który wygląda tak:liczba obserwacji w dzień w R

date<-c("2012-02-01", "2012-02-01", "2012-02-03", "2012-02-04", "2012-02-04", "2012-02-05", "2012-02-09", "2012-02-12", "2012-02-12") 
var<-c("a","b","c","d","e","f","g","h","i") 
df1<-data.frame(date,var) 

Chciałbym utworzyć drugą dataframe która tabularyzować liczbę obserwacji muszę każdego dnia. W tym dataframe, terminy, które nie są wymienione dostanie zero ... powodując coś takiego:

date<-c("2012-02-01","2012-02-02","2012-02-03","2012-02-04","2012-02-05","2012-02-06","2012-02-07","2012-02-08","2012-02-09","2012-02-10","2012-02-11","2012-02-12") 
num<-c(2,0,1,2,1,0,0,0,1,0,0,2) 
df2<-data.frame(date,num) 

Próbowałem wiele rzeczy z funkcji zbiorczej, ale nie można dowiedzieć się, jak zawierają daty bez obserwacji (zer).

+0

+1 dla powtarzalny przykład! – mnel

Odpowiedz

2

Tutaj podejście używając data.table

library(data.table) 
DF1 <- as.data.table(df1) 
# coerce date to a date object 
DF1[, date := as.IDate(as.character(date), format = '%Y-%m-%d')] 
# setkey for joining 
setkey(DF1, date) 

# create a data.table that matches with a data.table containing 
# a sequence from the minimum date to the maximum date 
# nomatch = NA includes those non-matching. 
# .N is the number of rows in the subset data.frame 
# this is 0 when there are no matches 
DF2 <- DF1[J(DF1[,seq(min(date), max(date), by = 1)]), .N, nomatch = NA] 
DF2 

      date N 
1: 2012-02-01 2 
2: 2012-02-02 0 
3: 2012-02-03 1 
4: 2012-02-04 2 
5: 2012-02-05 1 
6: 2012-02-06 0 
7: 2012-02-07 0 
8: 2012-02-08 0 
9: 2012-02-09 1 
10: 2012-02-10 0 
11: 2012-02-11 0 
12: 2012-02-12 2 

podejście używając reshape2::dcast

Jeśli upewnić się, że kolumna date ma poziomy dla każdego dnia, które chcesz tabularyzować

df1$date <- with(df1, factor(date, levels = as.character(seq(min(as.Date(as.character(date))), max(as.Date(as.character(date))), by = 1)))) 


df2 <- dcast(df1, date~., drop = FALSE) 
+0

+1 Dobra odpowiedź. Ale dlaczego "przez = 1"? –

+0

Jest to część połączenia z sek. – mnel

+1

Ups, przymglone oczy dziś rano;) –

0

Ostatnio zajmowałem się czymś l Ike to. Chciałbym utworzyć ramkę danych ze wszystkimi datami, które chcesz wziąć pod uwagę i użyć funkcji merge(), aby zrobić to, co sugerujesz.

df1$date <- as.Date(df1$date, format = "%Y-%m-%d") 
newdates <- data.frame(date=seq(as.Date('2012-02-01'),as.Date('2012-02-12'),1)) 
df2 <- merge(df1, newdates, by = "date", all = TRUE) 

The all = TRUE jest tutaj bardzo ważny, ponieważ wprowadza NA s gdzie df1 i df2 nie pasują do góry zamiast usuwania tych wystąpień.

Następnie użyj pakietu plyr dostać powodów:

library(plyr) 
ddply(df2, "date", function(x) sum(!is.na(x$var))) 

ten dzieli df2 na grupy według unikalnych wartościach df2$date, a następnie stwierdza, jak wiele wartości df2$var nie były NA, a następnie zwraca ten numer wraz z unikalną wartość df2$date reprezentuje.

0

Pobierz indeksu do formatu Postxct, a następnie:

counts <- data.frame(table(as.Date(index(my_data_frame))))

Powiązane problemy