web-dev-qa-db-fra.com

Agréger les données quotidiennes aux intervalles mois / année

Je n'ai pas souvent à travailler avec des dates en R, mais j'imagine que c'est assez facile. J'ai une colonne qui représente une date dans une trame de données. Je veux simplement créer un nouveau dataframe qui résume une 2ème colonne par mois/année en utilisant la date. Quelle est la meilleure approche?

Je veux une deuxième trame de données afin de pouvoir la nourrir dans un tracé.

Toute aide que vous pourrez apporter sera grandement appréciée!

EDIT: Pour référence:

> 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
53
Btibert3

Il existe probablement une solution plus élégante, mais la division en mois et années avec strftime() puis aggregate() ing devrait le faire. Remontez ensuite la date du tracé.

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 = "-"))
37
kmm

Je le ferais avec lubridate et plyr, en arrondissant les dates au mois le plus proche pour les rendre plus faciles à tracer:

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))
47
hadley

Un peu tard dans le jeu, mais une autre option serait d'utiliser 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))]

cela donne:

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

Si vous voulez des noms au lieu de chiffres pour les mois, vous pouvez utiliser:

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

cela donne:

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

Comme vous le voyez, cela donnera les noms des mois dans la langue de votre système (qui est le néerlandais dans mon cas).


Ou en utilisant une combinaison de lubridate et dplyr:

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

Données utilisées:

# 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))
16
Jaap

Utilisez simplement le paquet xts pour cela.

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)

où FUN est une fonction avec laquelle vous agrégez des données (par exemple somme)

8
Galina Alperovich

Vous pouvez le faire comme:

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

J'ai une fonction monyr que j'utilise pour ce genre de choses:

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

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

Vous pouvez modifier le as.Date à la fin de as.POSIXct pour correspondre au format de date dans vos données. La synthèse par mois consiste alors simplement à utiliser l'agrégat/par/etc.

3
Hong Ooi

De plus, étant donné que vos séries chronologiques semblent être au format xts, vous pouvez agréger vos séries chronologiques quotidiennes en une série chronologique mensuelle en utilisant la fonction moyenne comme celle-ci:

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

Voici une option dplyr:

library(dplyr)

df %>% 
  mutate(date = as.Date(date)) %>% 
  mutate(ym = format(date, '%Y-%m')) %>% 
  group_by(ym) %>% 
  summarize(ym_mean = mean(x))
0
sbha

Encore une solution:

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

Pour le tracé, vous pouvez utiliser barplot:

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