2011-05-19 23 views
41

A menudo no tengo que trabajar con fechas en R, pero me imagino que esto es bastante fácil. Tengo una columna que representa una fecha en un marco de datos. Simplemente quiero crear un nuevo marco de datos que resuma una 2da columna por Mes/Año usando la fecha. ¿Cuál es el mejor enfoque?Intervalos de datos diarios agregados a intervalos de Mes/Año

Quiero un segundo marco de datos para poder alimentarlo a un diagrama.

¡Cualquier ayuda que pueda proporcionar será muy apreciada!

EDIT: Como referencia:

> str(temp) 
'data.frame': 215746 obs. of 2 variables: 
$ date : POSIXct, format: "2011-02-01" "2011-02-01" "2011-02-01" ... 
$ amount: num 1.67 83.55 24.4 21.99 98.88 ... 

> head(temp) 
     date amount 
1 2011-02-01 1.670 
2 2011-02-01 83.550 
3 2011-02-01 24.400 
4 2011-02-01 21.990 
5 2011-02-03 98.882 
6 2011-02-03 24.900 
+0

@ Bibert3 ¿podría decirnos en qué formato están sus fechas? POSIX? ¿personaje? –

Respuesta

29

Probablemente haya una solución más elegante, pero dividiéndola en meses y años con strftime() y luego aggregate() debería hacerlo. Luego vuelva a armar la fecha para trazar.

x <- as.POSIXct(c("2011-02-01", "2011-02-01", "2011-02-01")) 
mo <- strftime(x, "%m") 
yr <- strftime(x, "%Y") 
amt <- runif(3) 
dd <- data.frame(mo, yr, amt) 

dd.agg <- aggregate(amt ~ mo + yr, dd, FUN = sum) 
dd.agg$date <- as.POSIXct(paste(dd.agg$yr, dd.agg$mo, "01", sep = "-")) 
2

Tengo una función monyr que utilizo para este tipo de cosas:

monyr <- function(x) 
{ 
    x <- as.POSIXlt(x) 
    x$mday <- 1 
    as.Date(x) 
} 

n <- as.Date(1:500, "1970-01-01") 
nn <- monyr(n) 

Puede cambiar el as.Date al final de as.POSIXct para que coincida con el formato de fecha en sus datos. Resumir por mes es simplemente una cuestión de usar agregado/por/etc.

43

lo haría con lubridate y plyr, redondeando las fechas hasta el mes más próximo para que sean más fáciles de Terreno:

library(lubridate) 
df <- data.frame(
    date = today() + days(1:300), 
    x = runif(300) 
) 
df$my <- floor_date(df$date, "month") 

library(plyr) 
ddply(df, "my", summarise, x = mean(x)) 
+2

O con dplyr, la última línea sería 'summarize (df, x = mean (my))'. – Fato39

0

Una solución más:

rowsum(temp$amount, format(temp$date,"%Y-%m")) 

Para trama que podría usar barplot:

barplot(t(rowsum(temp$amount, format(temp$date,"%Y-%m"))), las=2) 
4

Puede hacerlo como:

short.date = strftime(temp$date, "%Y/%m") 
aggr.stat = aggregate(temp$amount ~ short.date, FUN = sum) 
11

Un poco tarde al juego, pero otra opción sería utilizar data.table:

library(data.table) 
setDT(temp)[, .(mn_amt = mean(amount)), by = .(yr = year(date), mon = months(date))] 

# or if you want to apply the 'mean' function to several columns: 
# setDT(temp)[, lapply(.SD, mean), by=.(year(date), month(date))] 

esto da:

 yr  mon mn_amt 
1: 2011 februari 42.610 
2: 2011 maart 23.195 
3: 2011 april 61.891 

Si quieren nombres en lugar de números para los meses, puede usar:

setDT(temp)[, date := as.IDate(date) 
      ][, .(mn_amt = mean(amount)), by = .(yr = year(date), mon = months(date))] 

esto da:

 yr  mon mn_amt 
1: 2011 februari 42.610 
2: 2011 maart 23.195 
3: 2011 april 61.891 

Como se puede ver que esto le dará los nombres de los meses en el idioma del sistema (que es holandés en mi caso).


o utilizando una combinación de lubridate y dplyr:

temp %>% 
    group_by(yr = year(date), mon = month(date)) %>% 
    summarise(mn_amt = mean(amount)) 

datos utilizados:

# example data (modified the OP's data a bit) 
temp <- structure(list(date = structure(1:6, .Label = c("2011-02-01", "2011-02-02", "2011-03-03", "2011-03-04", "2011-04-05", "2011-04-06"), class = "factor"), 
         amount = c(1.67, 83.55, 24.4, 21.99, 98.882, 24.9)), 
        .Names = c("date", "amount"), class = c("data.frame"), row.names = c(NA, -6L)) 
7

sólo tiene que utilizar el paquete XTS para esto.

library(xts) 
ts <- xts(temp$amount, as.Date(temp$date, "%Y-%m-%d")) 

# convert daily data 
ts_m = apply.monthly(ts, FUN) 
ts_y = apply.yearly(ts, FUN) 
ts_q = apply.quarterly(ts, FUN) 

donde la diversión es una función de los datos que agregados con (por ejemplo, suma)

+0

¿por qué una respuesta por separado? es mejor agregar esto como una alternativa a su respuesta anterior imo – Jaap

1

Además, dado que sus series de tiempo parecen estar en formato XTS, puede agregar su serie de tiempo diario a un mes serie de tiempo que usa la función media como esta:

d2m <- function(x) { 
    aggregate(x, format(as.Date(zoo::index(x)), "%Y-%m"), FUN=mean) 
} 
Cuestiones relacionadas