Ejemplo 1: de mensual
a trimestral
La
función aggregate permite modificar (agregando) la frecuencia
de los datos. En los ejemplos siguientes se muestra como convertir de mensual a
trimestral la data. En caso de querer convertirla en semestral o anual, solo es
necesario cambiar el argumento nfrequency a los valores correspondientes.
set.seed(2)
price_sim
<- ts(5+cumsum(rnorm(100)), start = c(2010, 1), frequency = 12)
head(price_sim)
[1]
4.540211 5.158137 4.437714 3.854202 4.070527 5.315518
p_mean <- aggregate(price_sim, nfrequency = 4,
mean)
Qtr1 Qtr2 Qtr3
Qtr4
2010
4.755600 4.736043 6.007220
7.717201
p_sum <- aggregate(price_sim, nfrequency = 4, sum)
Qtr1
Qtr2 Qtr3 Qtr4
2010 14.266800 14.208130 18.021661 23.151604
p_var <- aggregate(price_sim, nfrequency = 4, sd)
p_ult <-
aggregate(price_sim, nfrequency = 4, function(x) tail(x,1))
p_prime
<- aggregate(price_sim, nfrequency = 4, function(x) x[1])
p_ran <-
aggregate(price_sim, nfrequency = 4, range)
p_ran2
<- aggregate(price_sim, nfrequency = 4, function(x) range(x)/2)
Ahora,
usando la maravilla de tidyverse agregamos la serie combinando las
funciones group_by y summarise. La primera de esta permite
agrupar nuestros datos según el criterio que necesitemos, mensual, anual,
semestral, etc; mientras la segunda permite incluir la agregación que
necesitemos promedio, valores máximo, ...:
library(tidyverse)
library(zoo)
data.frame(price_sim)
%>%
mutate(trimestre = as.yearqtr(time(price_sim),
format = "Q")) %>%
group_by(trimestre) %>%
summarise(p_mean = mean(price_sim),
p_sum = sum(price_sim),
p_var = sd(price_sim),
p_ult = last(price_sim),
p_prime = first(price_sim),
p_ran =
max(price_sim)-min(price_sim),
p_ran2 = (max(price_sim)+min(price_sim))/2)
# A tibble:
34 x 8
trimestre p_mean p_sum p_var p_ult p_prime p_ran p_ran2
<yearqtr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2010 Q1
4.76 14.3 0.974 5.88
4.10 1.77 4.99
2 2010 Q2
4.74 14.2 0.0667 4.80
4.75 0.132 4.73
3 2010 Q3
6.01 18.0 1.08 7.25
5.51 1.98 6.26
4 2010 Q4
7.72 23.2 0.718 8.51
7.11 1.40 7.81
5 2011 Q1
8.02 24.1 0.895 8.86
8.12 1.78 7.97
6 2011 Q2
7.15 21.4 0.518 7.46
6.55 0.914 7.01
7 2011 Q3
9.46 28.4 1.35 11.0
8.48 2.52 9.74
8 2011 Q4
11.5 34.5 1.78 13.3
9.80 3.54 11.6
9 2012 Q1
11.9 35.6 1.30 11.4
13.3 2.45 12.1
10 2012
Q2 11.4 34.2 0.560
11.9 10.8 1.08
11.3
# ... with
24 more rows
Ejemplo 2: de diario
a semanal
Adicionalmente
podemos estar interesado en llevar datos en frecuencia diaria a semanales o
mensuales, siendo la clave el elemento de agregación de las series. En el
siguiente ejemplo se crean las variables semana, mes, año, … con el fin de
obtener distintas agregaciones que nos permiten modificar la
variable que incluimos como argumento en el comando by_group, por esta razón se colocan
diversos niveles de agregación.
Generamos
datos diarios y colocamos las distintas demarcaciones temporales, es decir,
podemos obtener el día, el día del mes, mes, trimestre… estas variables nos permitirán
obtener la frecuencia nueva que necesitamos:
library(lubridate)
price_sim <- ts(5+cumsum(rnorm(1e3)), start =
c(2015,1,1), frequency = 365)
fechas
<- seq(as.Date("2010/1/1"), by="days", length.out = 1e3)
data_diaria
<- data.frame(price_sim, fecha = as.Date(fechas)) %>%
mutate(dia_mes = format(fecha,
"%d"),
dia_sem = format(fecha,
"%A"),
dia_sem_num = format(fecha,
"%w"),
semana = format(fecha,
"%W"),
dia_labor = (!(dia_sem_num %in%
c(0,6)))*1,
mes = format(fecha,
"%B"),
mes_num = as.numeric(format(fecha,
"%m")),
tri = format(fecha,
"%Q"),
semestre = ifelse(mes_num<=6, 1,2),
anio = format(fecha,
"%Y")
)
head(data_diaria,10)
price_sim fecha dia_mes dia_sem dia_sem_num semana dia_labor mes mes_num tri semestre anio
1 6.074459 2010-01-01 01
viernes 5 00
1 enero 1 Q
1 2010
2 6.335057 2010-01-02 02
sábado 6 00
0 enero 1 Q
1 2010
3 6.020785 2010-01-03 03
domingo 0 00
0 enero 1 Q
1 2010
4 5.271155 2010-01-04 04
lunes 1 01
1 enero 1 Q
1 2010
5 4.408957 2010-01-05 05
martes 2 01
1 enero 1 Q 1 2010
6 6.456997 2010-01-06 06 miércoles 3
01 1 enero 1
Q 1 2010
7 7.396917 2010-01-07 07
jueves 4 01
1 enero 1 Q
1 2010
8 9.405604 2010-01-08 08
viernes 5 01
1 enero 1 Q
1 2010
9 8.984231 2010-01-09 09
sábado 6 01
0 enero 1 Q
1 2010
10 8.633396 2010-01-10 10
domingo 0 01
0 enero 1 Q
1 2010
Ahora
queremos convertir los datos a semanales solo debemos indicarle que esta es la
variable de agregación que necesitamos. Como R enumera cada semana dentro de un año, debemos especificarle que necesitamos que la agrupe por año, para que no nos junte todas las primeras semanas de cada año. Se coloca el ejemplo con el promedio,
luego aplican todas las funciones vista en la agregación de meses a trimestres
vista en la sección anterior. Note que sem_media y sem_media1 arrojan el promedio semanal y el
promedio de la semana solo para lunes a viernes, usando la variable binaria de dias laborales:
data_diaria
%>%
group_by(anio,semana) %>%
mutate(sem_media = mean(price_sim),
sem_madia1 =
mean(price_sim[dia_labor==1]))%>%
select(price_sim,starts_with("sem"),-semestre)
# A tibble: 1,000 x 5
# Groups:
anio, semana [146]
anio
price_sim semana sem_media sem_madia1
<chr> <dbl> <chr> <dbl> <dbl>
1 2010 6.07 00 6.14 6.07
2 2010
6.34 00 6.14 6.07
3 2010
6.02 00 6.14 6.07
4 2010
5.27 01 7.22 6.59
5 2010
4.41 01 7.22 6.59
6 2010
6.46 01 7.22 6.59
7 2010
7.40 01 7.22 6.59
8 2010
9.41 01 7.22 6.59
9 2010
8.98 01 7.22 6.59
10
2010 8.63 01 7.22 6.59
# ... with
990 more rows
Note
que en el ejemplo anterior a cada día le colocamos el promedio de la semana,
pero si quisiéramos solamente obtener el promedio semanal, necesitamos agregar la semana tomando un día en específico,
por ejemplo, el lunes:
data_semanal <- data_diaria %>%
group_by(anio,semana) %>%
summarise(mean_sem_stot = sum(price_sim),
mean_sem_mtot = mean(price_sim),
mean_sem_lab = mean(price_sim[dia_labor==1]),
lunes =
mean(price_sim[dia_sem=="lunes"]),
max_sem_lab = max(price_sim[dia_labor==1]),
min_sem_lab = min(price_sim[dia_labor==1]))
head(data_semanal,5)
# A tibble: 5 x 8
# Groups: anio
[1]
anio semana mean_sem_stot mean_sem_mtot
mean_sem_lab lunes max_sem_lab
min_sem_lab
<chr>
<chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 2010 00 18.4 6.14 6.07 NaN 6.07 6.07
2 2010 01 50.6 7.22 6.59
5.27 9.41 4.41
3 2010 02 63.4 9.05 8.35
7.61 9.75 7.36
4 2010 03 93.2 13.3 12.7
12.6 13.3 11.9
5 2010 04 89.1 12.7 13.5
13.5 14.1 12.3
Finalmente mostramos como extraraer los elementos de una serie temporal u objeto ts. Se colocan algunos ejemplos (en
internet hay un montón adicionales).
price_sim <-
ts(5+cumsum(rnorm(1e3)), start = c(2015,1,1), frequency = 365)
data.frame(price_sim) %>%
mutate(fecha =
time(price_sim),
dia_semana =
format(as.yearmon(time(price_sim)), "%A"),
dia_mes =
format(as.yearmon(time(price_sim)), "%d"),
semana =
format(as.yearmon(time(price_sim)), "%W"),
mes =
as.yearmon(time(price_sim)),
mes_num =
as.numeric(format(mes, "%m")),
trimestre =
as.yearqtr(time(price_sim), format = "Q"),
semestre =
ifelse(mes_num<=6, 1,2),
anio =
as.integer(time(price_sim))
) %>%
head()
price_sim fecha dia_semana dia_mes semana mes mes_num trimestre semestre anio
1 5.468767 2015.000 jueves
01 00 ene. 2015 1
2015 Q1 1 2015
2 6.701727 2015.003 jueves
01 00 ene. 2015 1
2015 Q1 1 2015
3 5.160069 2015.005 jueves
01 00 ene. 2015 1
2015 Q1 1 2015
4 7.149561 2015.008 jueves
01 00 ene. 2015 1
2015 Q1 1 2015
5 7.394542 2015.011 jueves
01 00 ene. 2015 1
2015 Q1 1 2015
6 8.185899 2015.014 jueves
01 00 ene. 2015 1
2015 Q1 1 2015