2002
2004
2006
2008
2010
2012
2014
60
70
80
90
110
130
ipi Estimado LM Estimado RBSUna manera de obtener pronosticos en el caso de la regresión RBS, es generar los correspondientes armónicos y utilizar los coeficientes de la regresión RBS para componer el pronostico.
Por pasos:
a) Convertimos al dominio de tiempo cada regresor (cada columna de la matriz X)
b) Se reliza la estimación en el dominio del tiempo la regresión MCO X1t= ˆβ0+ ˆβ1t+ ˆβ1t2y su pronóstico
c) Se reliza la estimación en el dominio del tiempo la regresión MCO X2t= ˆβ0+ ˆβ1cos(2∗πtT ) y su pronóstico
d) Se reliza la estimación en el dominio del tiempo la regresión MCO X3t= ˆβ0+ ˆβ1sin(2∗πtT ) y su pronostico
e) Se reliza la estimación en el dominio del tiempo la regresión MCO X4t= ˆβ0+ ˆβ1cos(4∗πtT ) y su pronóstico
f) Se reliza la estimación en el dominio del tiempo la regresión MCO X5t= ˆβ0+ ˆβ1sin(4∗πtT ) y su pronostico
g) y sucesivamente . . . .
h) Se combinan las series pronosticadas con los coeficientes que resultan de la regresión en el dominio de la frecuencia.
Ejemplo 11
A continuación se realiza un ejemplo para el IPI de Cantabria, utilizando los dos primeros armónicos.
# REGRESION FILTRANDO LAS ALTAS FRECUENCIAS
S2 <- S1[1:5,]
X <- as.matrix(S2) X <- t(X)
rbs.fit.2=lm(ipi.1~0+X)
## ## Call:
## lm(formula = ipi.1 ~ 0 + X) ##
## Residuals:
## Min 1Q Median 3Q Max
## -60.204 -4.326 -0.237 1.651 65.231 ##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|) ## X1 12.16502 0.10704 113.646 < 2e-16 *** ## X2 -0.01543 0.10793 -0.143 0.8865 ## X3 0.16244 0.10615 1.530 0.1283 ## X4 0.06540 0.10725 0.610 0.5430 ## X5 -0.44072 0.10683 -4.125 6.46e-05 *** ## X6 -0.05344 0.10711 -0.499 0.6186 ## X7 0.26225 0.10697 2.452 0.0155 * ## X8 0.19221 0.10706 1.795 0.0748 . ## X9 -0.12187 0.10701 -1.139 0.2568 ## X10 -0.08563 0.10703 -0.800 0.4251 ## X11 0.03593 0.10702 0.336 0.7376 ## X12 0.05775 0.10698 0.540 0.5902 ## X13 0.05649 0.10685 0.529 0.5979 ## X14 -0.04020 0.10680 -0.376 0.7072 ## --- ## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ##
## Residual standard error: 10.86 on 134 degrees of freedom ## Multiple R-squared: 0.9898, Adjusted R-squared: 0.9888 ## F-statistic: 932.6 on 14 and 134 DF, p-value: < 2.2e-16
# Tendencia cuadrática
T=148
n=12
X.1=gdt(X[,1])
z.1=c(lm(X.1~t+t2)$fitted,predict(lm(X.1~t+t2),data.frame(t=seq(from=T+1, to=T+n),t2=seq(from=T+1, to=T+n)^2)))
plot(z.1,type="l", col="red") lines(X.1, type="p")
0
50
100
150
7.0
7.5
8.0
8.5
Index
z.1
# Armonico 1 X.2.1=gdt(X[,2])z.2.1=c(lm(X.2.1~cos(2*pi*t/T))$fitted,predict(lm(X.2.1~cos(2*pi*t/T)),data.frame(t=seq(from=T+1, to=T+n))))
plot(z.2.1,type="l", col="red") lines(X.2.1, type="p")
0
50
100
150
−10
−5
0
5
10
Index
z.2.1
X.2.2=gdt(X[,3])z.2.2=c(lm(X.2.2~sin(2*pi*t/T))$fitted,predict(lm(X.2.2~sin(2*pi*t/T)),data.frame(t=seq(from=T+1, to=T+n))))
plot(z.2.2,type="l", col="red") lines(X.2.2, type="p")
0
50
100
150
−10
−5
0
5
10
Index
z.2.2
# Armónico 2 X.3.1=gdt(X[,4])z.3.1=c(lm(X.3.1~cos(4*pi*t/T))$fitted,predict(lm(X.3.1~cos(4*pi*t/T)),data.frame(t=seq(from=T+1, to=T+n))))
plot(z.3.1,type="l", col="red") lines(X.3.1, type="p")
0
50
100
150
−10
−5
0
5
10
Index
z.3.1
X.3.2=gdt(X[,5])z.3.2=c(lm(X.3.2~sin(4*pi*t/T))$fitted,predict(lm(X.3.2~sin(4*pi*t/T)),data.frame(t=seq(from=T+1, to=T+n))))
plot(z.3.2,type="l", col="red") lines(X.3.2, type="p")
0
50
100
150
−10
−5
0
5
10
Index
z.3.2
# Pronostico serie de dos armónicos
fit.2=rbs.fit.2$coefficients[1]*z.1+rbs.fit.2$coefficients[2]*z.2.1+rbs.fit.2$coefficients[3]*z.2.2+rbs.fit.2$coefficients[4]*z.3.1+rbs.fit.2$coefficients[5]*z.3.2
plot(ipi)
lines(fit.2,col="red")
0
50
100
150
60
70
80
90
110
130
Index
ipi
Para obtener pronosticos con mayor precision, vamos a crea una serie de funciones que lo que hacer es generar indices para matriz ortogonal, W , con m adelantos.
Funcion MW2 (n,m)
MW2 <- function(n,m) {
# Author: Francisco Parra Rodriguez
# Some ideas from: Harvey, A.C. (1978), Linear Regression in the Frequency Domain, International Economic Review, 19, 507-512. # http://econometria.wordpress.com/2013/08/21/estimation-of-time-varying-regression-coefficients/ uno <- as.numeric (m:(n+m-1)) A <- matrix(rep(sqrt(1/n),n), nrow=1) if(n%%2==0){ for(i in 3:n-1){ if(i%%2==0) {
A1 <- matrix(sqrt(2/n)*cos(pi*(i)*(uno-1)/n), nrow=1)
A <- rbind(A,A1)} else {
A2 <- matrix(sqrt(2/n)*sin(pi*(i-1)*(uno-1)/n), nrow=1)
A <- rbind(A,A2) }}
AN <- matrix(sqrt(1/n)*(-1)^(uno+1), nrow=1)
A <- rbind(A,AN) A } else { for(i in 3:n-1){ if(i%%2==0) { A1 <- matrix(
sqrt(2/n)*cos(pi*(i)*(uno-1)/n), nrow=1)
A <- rbind(A,A1)} else {
A2 <- matrix(sqrt(2/n)*sin(pi*(i-1)*(uno-1)/n), nrow=1)
A <- rbind(A,A2) }}
AN <- matrix(
sqrt(2/n)*sin(pi*(n-1)*(uno-1)/n), nrow=1)
A <- rbind(A,AN) }
}
función gdf2(y,m)
La función gdf2, transforma al dominio de la frecuencia la serie temporal y adelanta en m periodos. gdf2 <- function(y,m) { a <- matrix(y,nrow=1) n <- length(y) A <- MW2(n,m) A%*%t(a) } función gdt2(y,m)
La función gdf2, transforma al dominio del tiempo la serie temporal y presentada en el dominio de la frecuencia, y adelantada en m periodos.
gdt2 <- function(y,m) {
# Author: Francisco Parra Rodriguez
a <- matrix(y,nrow=1) n <- length(y) A <- MW2(n,m) t(A)%*%t(a) }
Ejemplo 12
Utilizando estas nuevas matrices, la serie del IPI regional de Cantabria se pronosticaria con las altas frecuencias de esta forma:
# CREAMOS LA MATRIZ DE REGRESORES FILTRANDO LAS ALTAS FRECUENCIAS CON LA MATRIZ DE HARVEY
n=length(ipi)
M2 <- MW2(length(ipi),12)
z <- predict(lm(ipi~t+t2),data.frame(t=seq(from=11, to=n+10),t2=seq(from=11, to=n+10)^2))
cx <- M2%*%diag(z) cx <- cx%*%t(M2) id <- seq(1,n) S1 <- data.frame(cx) S2 <- S1[1:abs(2+(n/12)),] X <- as.matrix(S2) X <- t(X)
# PRONOSTICO FILTRANDO LAS ALTAS FRECUENCIAS
coef=t(as.matrix(rbs.fit$coefficients))
rbs.fit.3=coef%*%t(X) dim(rbs.fit.3)
## [1] 1 148
fit.3=gdt2(rbs.fit.3,12)
plot(window(ts(ipi,frequency = 12, start = c(2002, 1)),start = c(2003,1)),type="l",main="IPI.Cantabria",ylab="") lines(ts(z,frequency = 12, start = c(2003, 1)),type="l",col=2)
lines(ts(fit.3,frequency = 12, start = c(2003, 1)),type="l",col=3)
IPI.Cantabria
Time
2004
2006
2008
2010
2012
2014
60
70
80
90
110
130
ipi Estimado LM Estimado RBSLa regresión en el dominio de la frecuencia tambien puede utilizarse para modelos bivariados, la función “rdf” permite realizar dicha regresión.
funcion rdf(x,y)
El algoritmo de calculo “rdf” se realiza en las siguentes fases: a) Calcula el co-espectro de la serie “x” e “y”
Sea x un vector n x 1 el modelo transformado en el dominio de la frecuencia esta dado por: ˆx = W x. Sea y un vector n x 1 el modelo transformado en el dominio de la frecuencia esta dado por: ˆy = W y Denominando pjel ordinal del cross-periodograma de ˆx y ˆy en la frecuencia λj= 2πj/n, y ˆxj el j-th elemento
de ˆx y ˆyj el j-th elemento de ˆy, entonces
pj = ˆx2jˆy2j+ ˆx2j+1ˆy2j+1 ∀j= 1, ...n−12 pj = ˆx2jˆy2j ∀j= n2 −1
p0= ˆx1ˆy1
b) Ordena el co-espectro en base al valor absoluto de |pj|y genera un índice en base a ese orden para cada
coeficiente de fourier.
c) Calcula la matriz W xtInWT y la ordena en base al indice anterior.
d) Obtiene ˙e = W InWT˙u, incluyendo el vector correspondiente al parámetro constante, (1, 0, ...0)n, y
calucula el modelo utilizando los dos primeros regresores de la matriz W xtInWT reordenada y ampliada,
calcula el modelo para los 4 primeros, para los 6 primeros, hasta completar los n regresores de la matriz. e) Realiza el Test de Durbin (1967) a los modelos estimados, y selecciona aquellos en donde los et= WT˙e
Denominando pj al ordinal del periodograma de ˆa en la frecuencia λj= 2πj/n, y ˆaj el j-th elemento de ˆa, entonces pj= ˆa22j+ ˆa22j+1 ∀j= 1, ...n−1 2 pj= ˆa2 2j ∀j= n 2−1 p0= ˆa21
Entonces, el cuadrado de ˆa puede ser utilizado como un estimador consistente del periodograma de a. El test de Durbin está basado en el siguiente estadistico:
sj= Pj r=1pr Pm r=1pr donde m = 1 2npara n par y 1 2(n − 1) para n impar.
El estadístico sj ha de encontrarse entre unos límites inferior y superior de valores críticos que han sido
tabulados por Durbin (1969). Si bien, hay que tener presente que el valor p0 no se considera en el cálculo del
estadístico, esto es, p0= ˆv1= 0.
f) De todos ellos, elige aquél que tiene menos regresores. Si no encuentra modelo, devuelve la solución MCO.
rdf <- function (y,x) {
# Author: Francisco Parra Rodriguez # http://rpubs.com/PacoParra/24432 # Leemos datos en forma matriz
a <- matrix(y, nrow=1) b <- matrix(x, nrow=1) n <- length(a)
# calculamos el cros espectro mediante la funcion cperiodograma
cperiodograma <- function(y,x) {
# Author: Francisco Parra Rodriguez
# http://econometria.wordpress.com/2013/08/21/estimation-of-time-varying-regression-coefficients/ cfx <- gdf(y) n <- length(y) cfy <- gdf(x) if (n%%2==0) { m1x <- c(0) m2x <- c() for(i in 1:n){
if(i%%2==0) m1x <-c(m1x,cfx[i]) else m2x <-c(m2x,cfx[i])} m2x <- c(m2x,0)
m1y <- c(0) m2y <- c() for(i in 1:n){
if(i%%2==0) m1y <-c(m1y,cfy[i]) else m2y <-c(m2y,cfy[i])} m2y <-c(m2y,0)
frecuencia <- seq(0:(n/2))
frecuencia <- frecuencia-1
omega <- pi*frecuencia/(n/2)
periodos <- n/frecuencia
densidad <- (m1x*m1y+m2x*m2y)/(4*pi)
tabla$densidad[(n/2+1)] <- 4*tabla$densidad[(n/2+1)]
data.frame(tabla[2:(n/2+1),])}
else {m1x <- c(0) m2x <- c()
for(i in 1:(n-1)){
if(i%%2==0) m1x <-c(m1x,cfx[i]) else m2x <-c(m2x,cfx[i])} m2x <-c(m2x,cfx[n])
m1y <- c(0) m2y <- c()
for(i in 1:(n-1)){
if(i%%2==0) m1y <-c(m1y,cfy[i]) else m2y <-c(m2y,cfy[i])} m2y <-c(m2y,cfy[n])
frecuencia <- seq(0:((n-1)/2))
frecuencia <- frecuencia-1
omega <- pi*frecuencia/(n/2)
periodos <- n/frecuencia
densidad <- (m1x*m1y+m2x*m2y)/(4*pi)
tabla <- data.frame(omega,frecuencia, periodos,densidad) data.frame(tabla[2:((n+1)/2),])}
}
cper <- cperiodograma(a,b)
S1 <- data.frame(f1=cper$frecuencia,p=abs(cper$densidad))
S <- S1[with(S1, order(-p)), ]
id <- seq(2,n)
fpart = function(vec) { ret = vec - as.integer(vec) ret
}
evens=function(vec) {
stopifnot(class(vec)=="integer")
ret = vec[fpart(vec/2)==0]
ret } odds=function(vec) { stopifnot(class(vec)=="integer") ret = vec[fpart(vec/2)!=0] ret }
m1 <- cbind(S$f1*2,evens(id))
if (n%%2==0) {m2 <- cbind(S$f1[1:(n/2-1)]*2+1,odds(id))} else {m2 <- cbind(S$f1*2+1,odds(id))}
m <- rbind(m1,m2)
colnames(m) <- c("f1","id") m <- data.frame(m)
M=m[with(m, order(id)), ] M <- rbind(c(1,1),M)
# Obtenemos la funcion auxiliar (cdf) del predictor y se ordena segun el indice de las mayores densidades absolutas del co-espectro.
cx <- cdf(b) id <- seq(1,n)
S1 <- data.frame(cx,c=id)
S2 <- merge(M,S1,by.x="id",by.y="c") S3=S2[with(S2, order(f1)), ]
X1 <- S3[,3:m]
X1 <- rbind(C=c(1,rep(0,(n-1))),S3[,3:m])
# Se realizan las regresiones en el dominio de la frecuencia utilizando un modelo con constante, pendiente y los armonicos correspondientes a las frecuencias mas altas de la densidad del coespectro. Se realiza un test de durbin para el residuo y se seleccionan aquellas que son significativas.
par <- evens(id) i <- 1
D <- 1
resultado <- cbind(i,D) for (i in par) { X <- as.matrix(X1[1:i,]) cy <- gdf(a) B1 <- solve(X%*%t(X))%*%(X%*%cy) Y <- t(X)%*%B1 F <- gdt(Y) res <- (t(a) - F) T <- td(res)
L <- as.numeric(c(T$min<T$s2,T$s2<T$max))
LT <- sum(L) D <- LT-(n-1)
resultado1 <- cbind(i,D)
resultado <- rbind(resultado,resultado1) resultado}
resultado2 <-data.frame(resultado)
criterio <- resultado2[which(resultado2$D==0),]
sol <- as.numeric(is.na(criterio$i[1]))
if (sol==1) { X <- as.matrix(X1[1:2,]) cy <- gdf(a) B1 <- solve(X%*%t(X))%*%(X%*%cy) Y <- t(X)%*%B1 F <- gdt(Y) res <- (t(a) - F)
datos <- data.frame(cbind(t(a),t(b),F,res)) colnames(datos) <- c("Y","X","F","res")
list(datos=datos,Fregresores=t(X),Tregresores= t(MW(n))%*%t(X),Nregresores=criterio$i[1])
} else { X <- as.matrix(X1[1:criterio$i[1],]) cy <- gdf(a) B1 <- solve(X%*%t(X))%*%(X%*%cy) Y <- t(X)%*%B1 F <- gdt(Y) res <- (t(a) - F)
datos <- data.frame(cbind(t(a),t(b),F,res)) colnames(datos) <- c("Y","X","F","res") sse=sum(res^2)
gcv=length(res)*sse/((length(res)-dim(X)[1])^2)
list(datos=datos,Fregresores=t(X),Tregresores= t(MW(n))%*%t(X),Nregresores=criterio$i[1],sse=sse,gcv=gcv)}
}
funcion rdf2(y,x)
Realiza una aproximación entre la serie x e y con la tecnica RBS, utilizando como regresores una tendencia cuadráticas y los armónicos correspondientes a las K = √n
Dado que la variable exógena x no está expresada en forma periódica, debe de transformase o normalizarse en un intervalo de longitud menor que 2π;[0, 2π].
rdf2 <- function (y,x) {
# Author: Francisco Parra Rodríguez # Leemos datos en forma matriz
a <- matrix(y, nrow=1) b <- matrix(x, nrow=1)
n=ifelse(length(a)%%2==0,round(2*sqrt(length(a))),round(2*sqrt(length(a)-1)))
# Obtenemos la funcion auxiliar (cdf) del predictor y se ordena segun el indice de las mayores densidades absolutas del co-espectro.
cx <- cdf(b) cx <- cx[1:(n+1),]
cx.2=t(gdf(b^2))/10
X <- rbind(C=c(1,rep(0,(n-1))),cx,cx.2)
# Se realizan las regresiones en el dominio de la frecuencia utilizando un modelo con constante, pendiente y los arm?nicos correspondientes a las raiz de n frecuencias mas altas
cy <- gdf(a) B1 <- solve(X%*%t(X))%*%(X%*%cy) Y <- t(X)%*%B1 F <- gdt(Y) res <- (t(a) - F) datos <- data.frame(cbind(t(a),t(b),F,res)) colnames(datos) <- c("Y","X","F","res")
list(datos=datos,Fregresores=t(X),Tregresores= t(MW(length(a)))%*%t(X),Nregresores=n+3,Betas=B1)}
Ejemplo 13
A continuación va a realizarse una RBS con con datos anuales del PIB en Indices de Volumen y el consumo de energia final en España, correspondientes al periodo 1995-2018. En la libreria “descomponer”, las funciones “gdf” y “gdt” transforman las series del tiempo a la frecuencia y de la frecuencia al tiempo, siguiendo la
transformación sugerida por Harvey (1978).
# REGRESIÓN MINIMO CUADRADA
summary(lm(E~P)) ## ## Call: ## lm(formula = E ~ P) ## ## Residuals:
## Min 1Q Median 3Q Max
## -2040.3 -415.2 117.2 503.3 1314.2 ##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|) ## (Intercept) -2395.15 1266.05 -1.892 0.0718 .
## P 229.49 13.71 16.741 5.28e-14 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ##
## Residual standard error: 827.2 on 22 degrees of freedom ## Multiple R-squared: 0.9272, Adjusted R-squared: 0.9239 ## F-statistic: 280.3 on 1 and 22 DF, p-value: 5.285e-14
# TRANSFORMACION SERIES AL DOMINIO DE LA FRECUENCIA
K <- c(rep(1,24)) P.1 = gdf(P) E.1=gdf(E) K.1=gdf(K)
# REGRESIÓN EN EL DOMININO DE LA FRECUENCIA
summary(lm(E.1~0+K.1+P.1)) ## ## Call: ## lm(formula = E.1 ~ 0 + K.1 + P.1) ## ## Residuals:
## Min 1Q Median 3Q Max
## -3143.99 -37.02 149.20 307.14 1519.82 ##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|) ## K.1 -2395.15 1266.05 -1.892 0.0718 . ## P.1 229.49 13.71 16.741 5.28e-14 *** ## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 ##
## Residual standard error: 827.2 on 22 degrees of freedom ## Multiple R-squared: 0.9982, Adjusted R-squared: 0.9981 ## F-statistic: 6215 on 2 and 22 DF, p-value: < 2.2e-16
# REGRESION EN EL DOMINIO DE LA FRECUENCIA FILTRANDO LAS FRECUENCIAS RELEVANTES
rdf.mod=rdf(E,P) str(rdf.mod) ## List of 6
## $ datos :'data.frame': 24 obs. of 4 variables: ## ..$ Y : num [1:24] 12116 12655 13674 14202 15241 ... ## ..$ X : num [1:24] 66.5 68.2 70.8 73.9 77.2 ... ## ..$ F : num [1:24] 12181 12666 13436 14364 15269 ... ## ..$ res: num [1:24] -65.3 -11.2 238.2 -161.5 -28.3 ... ## $ Fregresores: num [1:24, 1:10] 1 0 0 0 0 0 0 0 0 0 ... ## ..- attr(*, "dimnames")=List of 2 ## .. ..$ : chr [1:24] "X1" "X2" "X3" "X4" ... ## .. ..$ : chr [1:10] "C" "1" "2" "3" ... ## $ Tregresores: num [1:24, 1:10] 0.204 0.204 0.204 0.204 0.204 ... ## ..- attr(*, "dimnames")=List of 2 ## .. ..$ : NULL ## .. ..$ : chr [1:10] "C" "1" "2" "3" ... ## $ Nregresores: num 10 ## $ sse : num 532799 ## $ gcv : num 65241
plot(ts(E,frequency = 1, start = 1995),type="l",main="Consumo Energia Final (Ktep).España",ylab="") lines(ts(fff.E$fitted, frequency = 1, start = 1995), type="l", col=2)
lines(ts(rdf.mod$datos$F, frequency = 1, start = 1995), type="l", col=3)
Consumo Energia Final (Ktep).España
Time
1995
2000
2005
2010
2015
12000
16000
20000
CEF Estimado FFF Estimado RBS
# REGRESION EN EL DOMINIO DE LA FRECUENCIA FILTRANDO LAS ALTAS FRECUENCIAS
rdf2.mod=rdf2(E,P)
## Warning in rbind(C = c(1, rep(0, (n - 1))), cx, cx.2): number of columns of ## result is not a multiple of vector length (arg 1)
str(rdf2.mod) ## List of 5
## $ datos :'data.frame': 24 obs. of 4 variables: ## ..$ Y : num [1:24] 12116 12655 13674 14202 15241 ... ## ..$ X : num [1:24] 66.5 68.2 70.8 73.9 77.2 ... ## ..$ F : num [1:24] 12166 12698 13383 14455 15204 ... ## ..$ res: num [1:24] -50.4 -43.4 291 -253.4 36.5 ... ## $ Fregresores: num [1:24, 1:13] 1 0 0 0 0 0 0 0 0 0 ... ## ..- attr(*, "dimnames")=List of 2 ## .. ..$ : NULL ## .. ..$ : chr [1:13] "C" "" "" "" ... ## $ Tregresores: num [1:24, 1:13] 0.2041 0.6273 0.0985 0.2887 -0.2959 ... ## ..- attr(*, "dimnames")=List of 2 ## .. ..$ : NULL ## .. ..$ : chr [1:13] "C" "" "" "" ... ## $ Nregresores: num 13 ## $ Betas : num [1:13, 1] 262.96 927.13 -40.19 1.21 -13.11 ... ## ..- attr(*, "dimnames")=List of 2 ## .. ..$ : chr [1:13] "C" "" "" "" ... ## .. ..$ : NULL
plot(ts(E,frequency = 1, start = 1995),type="l",main="Consumo Energia Final (Ktep).España",ylab="") lines(ts(rdf.mod$datos$F, frequency = 1, start = 1995), type="l", col=2)
legend("top", ncol=3, c("CEF","Estimado RBS","Estimado RBS2"), cex=0.6, bty="n", fill=c(1,2,3))
Consumo Energia Final (Ktep).España
Time
1995
2000
2005
2010
2015
12000
16000
20000
CEF Estimado RBS Estimado RBS2