Совокупные ежедневные данные по месяцам/годам
Мне не часто приходится работать с датами в R, но я думаю, что это довольно легко. У меня есть столбец, который представляет дату в кадре данных. Я просто хочу создать новый dataframe, который суммирует 2-й столбец по месяцам/годам с использованием даты. Каков наилучший подход?
Я хочу второй фреймворк данных, чтобы я мог передать его на график.
Любая помощь, которую вы можете предоставить, будет с благодарностью!
EDIT: для справки:
> 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
Ответы
Ответ 1
Возможно, существует более элегантное решение, но расщепляется на месяцы и годы с помощью strftime()
, а затем aggregate()
ing должно это делать. Затем соберите дату для печати.
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
Я бы сделал это с lubridate
и plyr
, округляя даты до ближайшего месяца, чтобы упростить их создание:
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))
Ответ 3
Немного поздно в игре, но другой вариант будет использовать 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))]
это дает:
yr mon mn_amt
1: 2011 februari 42.610
2: 2011 maart 23.195
3: 2011 april 61.891
Если вам нужны имена вместо чисел в течение месяцев, вы можете использовать:
setDT(temp)[, date := as.IDate(date)
][, .(mn_amt = mean(amount)), by = .(yr = year(date), mon = months(date))]
это дает:
yr mon mn_amt
1: 2011 februari 42.610
2: 2011 maart 23.195
3: 2011 april 61.891
Как вы видите, это даст имена месяца на вашем системном языке (в моем случае это голландский).
Или используя комбинацию lubridate
и dplyr
:
temp %>%
group_by(yr = year(date), mon = month(date)) %>%
summarise(mn_amt = mean(amount))
Используемые данные:
# example data (modified the OP 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))
Ответ 4
Просто используйте для этого пакет xts.
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)
где FUN - это функция, которую вы агрегируете данные с (например, суммой)
Ответ 5
Вы можете сделать это как:
short.date = strftime(temp$date, "%Y/%m")
aggr.stat = aggregate(temp$amount ~ short.date, FUN = sum)
Ответ 6
У меня есть функция monyr
, которую я использую для такого рода вещей:
monyr <- function(x)
{
x <- as.POSIXlt(x)
x$mday <- 1
as.Date(x)
}
n <- as.Date(1:500, "1970-01-01")
nn <- monyr(n)
Вы можете изменить as.Date
в конце на as.POSIXct
, чтобы соответствовать формату даты в ваших данных. Суммирование по месяцам - это просто вопрос использования aggregate/by/etc.
Ответ 7
Кроме того, учитывая, что ваши временные ряды выглядят в формате xts, вы можете суммировать ежедневные временные ряды с ежемесячным временным рядом, используя следующую среднюю функцию:
d2m <- function(x) {
aggregate(x, format(as.Date(zoo::index(x)), "%Y-%m"), FUN=mean)
}
Ответ 8
Еще одно решение:
rowsum(temp$amount, format(temp$date,"%Y-%m"))
Для сюжета вы можете использовать barplot
:
barplot(t(rowsum(temp$amount, format(temp$date,"%Y-%m"))), las=2)