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
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 = "-"))
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))
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))
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)
Vous pouvez le faire comme:
short.date = strftime(temp$date, "%Y/%m")
aggr.stat = aggregate(temp$amount ~ short.date, FUN = sum)
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.
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)
}
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))
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)