Zagreguj dane dzienne w odstępach miesięcznych/rocznych

Nieczęsto muszę pracować z datami w R, ale wyobrażam sobie, że jest to dość łatwe. Mam kolumnę, która reprezentuje datę w ramce danych. Po prostu chcę utworzyć nowy dataframe, który podsumowuje kolumnę 2nd przez miesiąc / rok za pomocą daty. Jakie jest najlepsze podejście?

Chcę drugą ramkę danych, żeby nakarmić nią fabułę.

Każda pomoc będzie bardzo mile widziana!

EDIT: dla odniesienia:

> 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
 61
Author: Jaap, 2011-05-19

9 answers

Jest prawdopodobnie bardziej eleganckie rozwiązanie, ale podział na miesiące i lata z strftime() i aggregate()ing powinien to zrobić. Następnie zmontuj datę do kreślenia.

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 = "-"))
 39
Author: kmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-19 01:42:59

Zrobiłbym to za pomocą lubridate i plyr, zaokrąglając daty do najbliższego miesiąca, aby ułatwić ich wykreślenie:

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))
 54
Author: hadley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-21 15:42:15

Trochę za późno na grę, ale inną opcją byłoby użycie 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))]

Daje to:

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

Jeśli chcesz nazwy zamiast liczb dla miesięcy, możesz użyć:

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

Daje to:

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

Jak widzisz, to da nazwy miesięcy w Twoim języku systemowym (który jest holenderski w moim przypadku).


Lub używając kombinacji lubridate i dplyr:

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

Użyte DANE:

# 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))
 20
Author: Jaap,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-02 17:30:15

Możesz to zrobić jako:

short.date = strftime(temp$date, "%Y/%m")
aggr.stat = aggregate(temp$amount ~ short.date, FUN = sum)
 9
Author: Galina Alperovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 15:07:27

Wystarczy użyć do tego pakietu 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)

Gdzie FUN jest funkcją, którą agregujesz dane (np. sumą)

 8
Author: Galina Alperovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-25 15:44:41

Mam funkcję monyr, której używam do tego typu rzeczy:

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

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

Możesz zmienić as.Date na końcu na as.POSIXct, aby dopasować format daty w swoich danych. Podsumowanie według miesięcy jest wtedy tylko kwestią użycia agregatu / według / itp.

 4
Author: Hong Ooi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-19 01:20:11

Oto dplyr Opcja:

library(dplyr)

df %>% 
  mutate(date = as.Date(date)) %>% 
  mutate(ym = format(date, '%Y-%m')) %>% 
  group_by(ym) %>% 
  summarize(ym_mean = mean(x))
 2
Author: sbha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-19 00:49:11

Ponadto, biorąc pod uwagę, że twoje szeregi czasowe wydają się być w formacie xts, możesz połączyć dzienny szereg czasowy z miesięcznym szeregiem czasowym za pomocą funkcji mean w następujący sposób:

d2m <- function(x) {
  aggregate(x, format(as.Date(zoo::index(x)), "%Y-%m"), FUN=mean)
}
 1
Author: dospring,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-15 10:23:18

Jeszcze jedno rozwiązanie:

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

Dla działki można użyć barplot:

barplot(t(rowsum(temp$amount, format(temp$date,"%Y-%m"))), las=2)
 0
Author: Marek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-22 20:58:35