set.seed(1)
require(forecast)
library(tscount)
library(ggplot2)
library(parameters)
library(tidyverse)
library(nlme)
library(scales)
library(ggforce)
library(kableExtra)
Events that occur in succession tend to be more similar than events that occur after a long separation. The extent to which a measured is determined by previous events is called temporal autocorrelation.
Long-term ecological studies are likely to deal with temporal autocorrelation biases once they have collected data over a long period of time in succession.
Despite my limited knowledge in time series analysis, I find this topic particularly interesting because it involves complex nuances that cannot be fully captured by simple generalized linear models. So, let’s explore how we can handle them.
In this post, I will demonstrate how to use the Tscount package and compare the performance with a more simple Autoregressive Generalized Linear Model (GLM). In case you are not familiar with GLMs please check here or here first. Because we need some knowledge about trend, moving average and how a time series looks like, I’ll first introduce these concepts then we start playing around with the Tscount package. If you’re already familiar with these concepts, feel free to skip ahead to the Autoregressive GLMs or Tscount package, here we go! sections
To make our script more redable I’ll use a lot the pipe
%>% command from tidyverse package. If you
are not familiar with pipes please check here and
here
We can use the Autocorrelation Function acf()and the
Partial Autocorrelation function pacf() to detected the
extent to which a observation is dependent to the previous
observations.
Thus, the acf() check how the observation is related to
different time-lags. So, at the time-lag 0, observation is compared to
itself and is always = 1. As the time-lag increases to 1, 2, and 3,
observation is correlated with 1 observation before, or 2, or 3,
respectively. Thus, if it is positively correlated it tends to look like
a stairs. See the ACF plot ts1 below.
On another hand, the Partial Autocorrelation function
pacf() decompose the contribution of each previous
observation. So, in the time-lag 1, we have the same value in the ACF
and PCAF function but at the time-lag 2 the correlation the extent to
which observation is related to two observations back in time is
discounted from the correlation at time-lag 1.
This is why the PCAF plot usually looks so different than the ACF. Both plots represent how a given observation is determined by previous observation. Below, we provide a table comparing both the ACF and PACF, we can see that the time-lag is equal at time-lag 1 and different therefore.
par(mfrow=c(1,2))
resultACF<-acf(ts1,xlim=c(0,15),ylim=c(-.4,1),main="ACF Plot ts1")
resultPACF<-pacf(ts1,xlim=c(1,14),ylim=c(-.4,1),main="PACF Plot ts1")
data.frame(time.lag=c(0,seq(1,5,1)),
ACF=round(resultACF$acf[1:6,,1],2),
PACF=c("NA",round(resultPACF$acf[1:5,,1],2)))%>%t()%>%kable(.,"html")%>%
kable_styling(full_width = F)
| time.lag | 0 | 1 | 2 | 3 | 4 | 5 |
| ACF | 1.00 | 0.79 | 0.49 | 0.28 | 0.14 | 0.06 |
| PACF | NA | 0.79 | -0.36 | 0.14 | -0.11 | 0.05 |
Modelling time-series is a broad field in statistics and there is a huge toolbox to handle the unique nuances existing in time series data, here, we will focus on the usage of the Tscount package but might be worth it to consider the ARIMA model. ARIMA model is the brief for “Autoregressive Integrated Moving Average” the idea of this model is consider an autoregressive component, a trend, and multiple moving averages in a single model.
The autoregressive component represents the extent to which a observation is related to previous observations;
A trend. Year after year, winters are colder than summers, but if you collect data long enough, you are likely to see that there is a general trend to increase the temperature in most parts of the world due to climatic changes. This is a kind of trend that can emerge in a time series.
Finally, the moving average. I think this is the most difficult concept to grasp. Fortunately (or unfortunately) we heard about it every day during the Pandemic outbreak. It is because, at least in Brazil, for some reason, there was a general sub notification of the Covid cases during the weekends. Thus, every weekend there were a general felling (and hope) that the cases were reducing but hereafter comes the Mondays and Tuesdays to boost the cases once again. Any discussion based on the number of cases by day were useless because the ups and downs were almost unpredictable. Instead, the discussion were about the Moving average of the last three days and also considering the whole week. Thus, the moving average is basically the mean number of cases during a given period of time (three days, or a week). So, don’t matter the particular ups and downs of a couple of days, but the multiple moving averaging along the trend.
You will probably see the ARIMA models denoted as ARIMA(p,d,q). The letters p, d and q represents exactly each one of the components aforementioned. So, p = Autoregressive component, differentiation (d) = trend, and q represents the moving average. Also keep in mind that that the autoregressive and moving average might have more than one parameter. For instance, observation might be correlated with the previous observation at some degree but every week days might be similar too. So, every Monday is more similar with other Mondays than Wednesdays. In this case we expect at least two autoregressive components and we call this an autoregressive model of order 2.
Remember our example about the heavy-rainy Friday being in the wet season? So, where is the season in the model we simulated?
That is right, the season component is missing! The aforementioned ARIMA model is non-seasonal and could not capture the variation of annual cycles, but there is also a Seasonal (S)ARIMA where the same p,d, and q components are applied to to different seasons and are denoted by the capital letters P, D, and Q as follow ARIMA(p,d,q)(P,D,Q).
Now you know that the ARIMA tool kit is complex enough, let’s stick in our non-seasonal ARIMA because it is exactly what we want since the Tscount package cannot handle the Season component directly. Of course, there is always a trick you can use to extent the functionalities of statistical analyses. Indeed, the documentation of the Tscount package handled the annual component in a analysis of killed drivers of light good vehicles in Great Britain due to the lack of seat belts by setting a autoregressive component related to 12 months. It was a great idea by the way.
Considering our time series, we can use the function
auto.arima() to automatically estimate autocorrelation,
trend, and moving average components.
arima.model1<-auto.arima(ts1)
arima.model1.tab<-arima.model1%>%parameters()%>%mutate_if(is.numeric,round,2)
arima.model1.tab
The Auto.arima function just nail it! This function
correctly estimated the autoregressive component at ar1 = 0.62 from
0.7and the moving average (ma1) = 0.54 from 0.5 in our simulate
data.
Now let’s plot our simulated time series followed by the timeseries
predicted by the auto.arima function.
data.frame(simulated=as.vector(ts1),auto.arima=fitted(arima.model1),dates=dates)%>%
pivot_longer(!dates, names_to = "timeseries", values_to = "Value")%>%
ggplot(., aes(x=dates, y=Value)) +
geom_line(aes(color=timeseries)) +
geom_point(shape=16,aes(color=timeseries))+
labs(x="Date", y="Value",color=NULL)+
scale_color_manual(values=c('tomato',"black"))+
scale_x_date(date_labels = "%b-%Y")+theme_classic(base_size =16)
Wow, that is so accurate! The auto.arima function did a pretty good job at the end! But what about if we are interested in using covariates? The sad news is that we cannot rely on the auto.arima function for testing the effect of covariates in the variable we are analysing.
The good news is the is several fancy models to do so, here, I will use a generalized Linear Model (GLM) framework!😊
To exemplify the use of an autoregressive GLM we will use data from Marquiz-Alves et al. 2023 PeerJ. In this example, the authors surveyed the Andean condors perching in a communal roost three times per weeks as well as the temperature and rainfall at the location.
Data is available in the supplementary material of this paper but here we will use a slightly modified version of it.
condor_data<-read.csv("Condor_data.csv",sep=";")
head(condor_data)
# We need to standardize the covariates so we can compare the conclusions in different models at the end.
condor_data$Temperature_stand<-as.vector(scale(condor_data$Temperature))
condor_data$Rainfall_stand<-as.vector(scale(condor_data$Rainfall))
The number of surveyed condors around the year tends to decrease dramatically. This coincides with the general trend of the temperature increasing.
par(mar=c(5,5,1,1))
plot(condor_data$Condors,type="b",col=NULL,xlab="Surveys days", ylab="Total condors surveyed",ylim=c(-10,40),pch=16,cex.lab=1.5,cex.axis=1.5)
barplot(condor_data$Rainfall, width = 1, space = 0, col=alpha("blue", 0.1),yaxt='n',add=T)
abline(a=0,b=0,col="grey",lty=2)
points(condor_data$Temperature,type="b",col="tomato",pch=16)
points(condor_data$Condors,type="b",col="black",pch=16)
legend(75, 40, legend=c("Condors", "Temperature","Rainfall"),
col=c("black", "tomato",alpha("blue", 0.2)), lty=1,lwd=c(1,1,7), cex=1.2)
But let’s look close. So, we will focus on surveys 1 to 20 and 60 to 80 to visually examine the behaviour of the total condors censused at different daily temperature and rainfall. We can see there is a general trend to increase the number of surveyed condors at higher temperature that is easier to detected on zooming surveys 1-20 but a rapid reduction on the number of surveyed condors after a rainy day, that is quite clear zooming surveys 50-70.
Particularly in days 60-80 the relationship with the temperature seems not so strong. What do you thing?
par(mfrow=c(1,2))
plot(condor_data$Condors[1:20],type="b",col=NULL,xlab="Surveys days", ylab="Total condors surveyed",ylim=c(-10,40),pch=16, main="Days 1-20")
barplot(condor_data$Rainfall[1:20], width = 1, space = 0, col=alpha("blue", 0.1),add=T)
abline(a=0,b=0,col="grey",lty=2)
points(condor_data$Temperature[1:20],type="b",col="tomato",pch=16)
points(condor_data$Condors[1:20],type="b",col="black",pch=16)
legend(10, 40, legend=c("Condors", "Temperature","Rainfall"),
col=c("black", "tomato",alpha("blue", 0.2)), lty=1,lwd=c(1,1,7), cex=1.2)
plot(condor_data$Condors[60:80],type="b",col=NULL,xlab="Surveys days", ylab="",ylim=c(-10,40),pch=16, main="Days 60-80")
barplot(condor_data$Rainfall[60:80], width = 1, space = 0, col=alpha("blue", 0.1),add=T,ylab="")
abline(a=0,b=0,col="grey",lty=2)
points(condor_data$Temperature[60:80],type="b",col="tomato",pch=16)
points(condor_data$Condors[60:80],type="b",col="black",pch=16)
legend(10, 40, legend=c("Condors", "Temperature","Rainfall"),
col=c("black", "tomato",alpha("blue", 0.2)), lty=1,lwd=c(1,1,7), cex=1.2)
This is now where autoregressive GLMs come to action! ARIMA models,
auto.arima() included, cannot handle covariates. So sad,
indeed! So we cannot use this super fancy and very accurate function to
rely our science stuffs 😞.
Fortunately, there is plenty of alternative to handle time series with covariates using the Generalized Linear Model framework. We will compare the performance of two alternative here.
nlme package.So, let’s check how surveys are autocorrelated in time.
par(mfrow=c(1,2))
acf(condor_data$Condors,main="Andean condor census")
pacf(condor_data$Condors,main="Andean condor census")
As we can see, there is a strong temporal autocorrelation in the Andean condor survey. When we check the partial autocorrelation function we see that a given observation is quite strong on the immediate previous observation, time-lag = 1, but also significantly associated to 2, 3 and 4 time-lags.
We will first check how this data behaviour under a simple GLM.We
will call this glm naive.glm
naive.glm<-glm(Condors ~ Temperature_stand + Rainfall_stand, family=poisson(),data=condor_data)
parameters(naive.glm)
There is a strong relationship between the surveyed condors and the temperature and rainfall in our model.
Now, let’s see how the model predicted the number of censused condors.
plot(condor_data$Condors,type="b",col=NULL,xlab="Surveys days", ylab="Total condors surveyed",ylim=c(-10,40),pch=16,cex.lab=1.5,cex.axis=1.5)
points(condor_data$Condors,type="b",col="black",pch=16)
points(fitted(naive.glm),type="b",col="blueviolet",pch=16)
barplot(condor_data$Rainfall, width = 1, space = 0, col=alpha("blue", 0.1),yaxt='n',add=T)
abline(a=0,b=0,col="grey",lty=2)
#points(condor_data$Temperature,type="b",col="tomato",pch=16)
#points(condor_data$Condors,type="b",col="black",pch=16)
legend(60, 40, legend=c("Condors", "Estimated naive glm","Rainfall"),
col=c("black", "blueviolet",alpha("blue", 0.2)), lty=1,lwd=c(1,1,7), cex=1.2)
Our naive glm did a pretty good job! However, when we check the residuals (figure below) we can see it has a significant temporal autocorrelation structure which is definitively something undesired. Just remember, that a good model the residuals MUST be independent (in time or space, here we are assessing just time).
layout(t(matrix(c(1,1,1,1,2,2,3,3),ncol=2)))
plot(residuals(naive.glm),type="b",col=NULL,xlab="Surveys days", ylab="Residuals",ylim=c(-5,8),pch=16,cex.lab=1.5,cex.axis=1.5)
points(residuals(naive.glm),type="b")
acf(residuals(naive.glm))
pacf(residuals(naive.glm))
So, let’s use another tool to see if we can handle this.
Once again, we have bad news!
In these usual packages we ecologists customary use, there is temporal correlation component available as far I know. The most close approach is to use a Generalised Least Square regression from the ‘nlme’ package. This is not a big problem as we can transform or count data by using the natural logarithm + 1 to correct for count dispersion common in count data. This is simple, works, but it is not very elegant. Here an amazing example on how to use Autoregressive GLS in Social Sciences.
#We need to inform a index of observations
ID=1:dim(condor_data)[1]
condor_data_ID<- as.data.frame(cbind(condor_data,ID))
modelGLSAR<-gls(log(Condors+1) ~ Temperature_stand + Rainfall_stand, correlation = corAR1(form=~ID),data=condor_data,method="ML")
We cannot directly compare models using transformed and non-transformed data, but again we can handle it.
To compare the AIC from transformed and non-transformed models, you must correct the AIC of the model where data was transformed by sum the AIC by 2*sum(logarithm of the data + 1). Check why on the stackoverflow
AIC_res<-AIC(naive.glm,modelGLSAR)
AIC_res$AIC[2]<-AIC_res$AIC[2] + sum(2*log(condor_data$Condors+1))
AIC_res%>%kable(.,"html")%>%kable_styling(full_width = F) #Note: kable and kable_styling is just a bautiful way to provide the table. You problable can remove this part of the code if you are not using Rmarkdown
| df | AIC | |
|---|---|---|
| naive.glm | 3 | 748.8869 |
| modelGLSAR | 5 | 550.8080 |
When we compare the goodness of fit of both approaches we find a clearly support over the autoregressive GLM over the naive GLM.
Well, we must also check the assumptions of our model and we can see that the residuals are finally autocorrelated. That is a great achievement!1
layout(t(matrix(c(1,1,1,1,2,2,3,3),ncol=2)))
plot(residuals(modelGLSAR,type="normalized"),type="b",col=NULL,xlab="Surveys days", ylab="Residuals",ylim=c(-3,3),pch=16,cex.lab=1.5,cex.axis=1.5)
points(residuals(modelGLSAR,type="normalized"),type="b")
acf(residuals(modelGLSAR,type="normalized"))
pacf(residuals(modelGLSAR,type="normalized"))
Now, let’s compare visually the performance of our naive glm and our autoregressive gls compared to the original dataset.
plot(condor_data$Condors,type="b",col=NULL,xlab="Surveys days", ylab="Total condors surveyed", ylim=c(-10,40), pch=16, cex.lab=1.5,cex.axis=1.5)
points(condor_data$Condors,type="b",col="black",pch=16)
points(fitted(naive.glm),type="b",col="blueviolet",pch=16)
points(expm1(fitted(modelGLSAR)),type="b",col="green",pch=16)
legend(70, 40, legend=c("Condors", "Estimated naive glm","Estimated GLSAR"),
col=c("black", "blueviolet",alpha("green", 0.2)), lty=1,lwd=c(1,1,7), cex=1.2)
Oh my! There is a clear under performing using the autoregressive GLS! We definitively must try something else once these results are not good enough to make the conclusions we desire. Now, it’s time to play around with the Tscount package!
Every component presented, we can now go to the Tscount package, which is very straightforward. There is a main function called tsglm that perform the GLM with an autoregressive component (also moving averaging if you need it).
The documentation of the tscount package provides numerous comparisons with much more fancy packages but with proportional complexity. I recommend reading it, but if this is the first time you are in touch to time series analyses, I suggest you to expend a bit more time navigating here and other the references I’m citing.
Back to the tscount, the major difference between our last models and tsglm is that we cannot use the syntax \(y = x1 + x2\) used in our previous model. I think that this syntax is pretty intuitive and I truly don’t understand what the challenges to implement something like this, however, it is as it is. Therefore, we need to group our covariates in a separate data.frame. Here, I will call it Betas.
Betas<-cbind(Temperature_stand= condor_data$Temperature_stand,
Rainfall_stand=condor_data$Rainfall_stand)
Betas%>%head()%>%t()%>%kable(.,"html")%>%
kable_styling(full_width = F)
| Temperature_stand | -0.6812912 | -0.3798905 | -0.3296570 | -0.7315246 | -1.0831588 | -3.1427302 |
| Rainfall_stand | -0.2867711 | -0.2867711 | -0.2867711 | -0.2867711 | -0.2867711 | -0.2867711 |
Once we have the regressors (our Betas) we can finally
perform the analyses using the Tscount package. So, let’s use
the function tsglm function!
glm_tscount<- tsglm(ts=condor_data$Condors, link="log",
model=list(past_obs=c(1)), distr="pois",xreg=Betas)
glm_tscount
##
## Call:
## tsglm(ts = condor_data$Condors, model = list(past_obs = c(1)),
## xreg = Betas, link = "log", distr = "pois")
##
## Coefficients:
## (Intercept) beta_1 Temperature_stand Rainfall_stand
## 0.6586 0.5106 -0.1653 -1.4631
Of course, we cannot forget to check the assumptions in our model.We
can just use plot(glm_tscount)to quick check the most
important assumptions in our model.
layout(t(matrix(c(1,1,1,1,2,2,3,3),ncol=2)))
plot(residuals(glm_tscount,type="pearson"),type="b",col=NULL,xlab="Surveys days", ylab="Residuals",ylim=c(-3,7),pch=16,cex.lab=1.5,cex.axis=1.5)
points(residuals(glm_tscount,type="pearson"),type="b")
acf(residuals(glm_tscount,type="pearson"))
pacf(residuals(glm_tscount,type="pearson"))
We will apply again the AIC and visually.
When we plot all models together, we can see that even if the naive GLM did a fair job to estimate the total condors surveyed, the Tscount has a superior accuracy. Using the Tscount the model could incorporate the high ocurrence of zeros at the end of the time series that coincide with the increasing in the rainfall.
plot(condor_data$Condors,type="b",col=NULL,xlab="Surveys days", ylab="Total condors surveyed", ylim=c(-10,40), pch=16, cex.lab=1.5,cex.axis=1.5)
points(condor_data$Condors,type="b",col="black",pch=16)
points(fitted(naive.glm),type="b",col="blueviolet",pch=16)
points(expm1(fitted(modelGLSAR)),type="b",col="green",pch=16)
points(fitted(glm_tscount),type="b",col="orange",pch=16)
legend(70, 40, legend=c("Condors", "Estimated naive glm","Estimated GLSAR","Estimated Tscount"),
col=c("black", "blueviolet","green","orange"), lty=1,lwd=c(1,1,1), cex=1.2)
Let’s take the same code lines we previously used to compute and make comparable the AICs for the naive.glm and modelGLSAR models. We just need to add the glm_tscount model here too.
AIC_res<-AIC(naive.glm,modelGLSAR,glm_tscount)
AIC_res$AIC[2]<-AIC_res$AIC[2] + sum(2*log(condor_data$Condors+1))
AIC_res%>%kable(.,"html")%>%kable_styling(full_width = F)
| df | AIC | |
|---|---|---|
| naive.glm | 3 | 748.8869 |
| modelGLSAR | 5 | 550.8080 |
| glm_tscount | 4 | 633.6192 |
At first glance we see that the Tscount package underperformed compared to the modelGLSAR. We made a huge achievement by accounting for the temporal autocorrelation, so, don’t let it down and don’t worry because we can also consider a negative binomial distribution to see if the model improve its performance.
The negative binomial distribution usually perform better than Poisson when we have highly dispersed data. The overdispersion in the condor dataset is likely due to few surveys that accounted over 30 individuals meanwhile a bunch of zero records.
glm_tscount_pois<-glm_tscount
glm_tscount_negbin<- tsglm(ts=condor_data$Condors, link="log",
model=list(past_obs=c(1)), distr="nbinom",xreg=Betas)
AIC_res<-AIC(naive.glm,modelGLSAR,glm_tscount_pois,glm_tscount_negbin)
AIC_res$AIC[2]<-AIC_res$AIC[2] + sum(2*log(condor_data$Condors+1))
AIC_res%>%kable(.,"html")%>%kable_styling(full_width = F)
| df | AIC | |
|---|---|---|
| naive.glm | 3 | 748.8869 |
| modelGLSAR | 5 | 550.8080 |
| glm_tscount_pois | 4 | 633.6192 |
| glm_tscount_negbin | 5 | 535.4569 |
This looks like the case here! The model using a negative binomial performed much better than other models. So, let’s consider it to drawn our conclusions hereafter.
Despite the major criticism about p-values, I like to report it as I think that it is become already intuitive for most of minimum trained researchers. However, I prefer to report the effect size and its respective confidence interval. If you wanna to check more about p-values and how we can better understand it, check this amazing source!
Because tsglm doesn’t provide the p-values, we find them using a normal approximation technique applied to the confidence interval from the parameters estimated by our model. The normal approximation is explained in detail here.
glm_tscount_t_list<-abs(as.vector(summary(glm_tscount_negbin)$coeff[,1]/summary(glm_tscount_negbin)$coeff[,2]))
#P-valor by normal approximation
glm_tscount_p_list<-exp(-0.717*abs(as.vector(glm_tscount_t_list)) -
0.416 * abs(as.vector(glm_tscount_t_list))^2)
glm_tscount_withP<-data.frame(summary(glm_tscount_negbin)$coeff,t_value=glm_tscount_t_list,p_value=glm_tscount_p_list)%>%round(4)
glm_tscount_withP
So, now, we see that temperature is no longer a super important variable. Indeed, only a very small evidence support the idea that the temperature determine the total number of surveyed condors. Now, let’s compare each model and their conclusions.
naive_glm_df<-naive.glm%>%parameters()%>%as.data.frame()
naive_glm_df<-naive_glm_df[,c(1,2,3,9)]
naive_glm_df$Method<- "Naive GLM"
modelGLSAR.df<-modelGLSAR%>%parameters()%>%as.data.frame()
modelGLSAR.df<-modelGLSAR.df[,c(1,2,3,9)]
modelGLSAR.df$Method<- "GLS AR1"
glm_tscount_df<-glm_tscount_withP%>%
add_rownames(., var = "Parameter")%>%
data.frame()
## Warning: `add_rownames()` was deprecated in dplyr 1.0.0.
## i Please use `tibble::rownames_to_column()` instead.
glm_tscount_df<-glm_tscount_df[,c(1,2,3,7)]
colnames(glm_tscount_df)<-c("Parameter","Coefficient","SE","p")
glm_tscount_df$Method<- "Tscount"
rbind(naive_glm_df,modelGLSAR.df,glm_tscount_df)%>%mutate_if(.,is.numeric,round,3)%>%kable(.,"html")%>%kable_styling(full_width = F)
| Parameter | Coefficient | SE | p | Method |
|---|---|---|---|---|
| (Intercept) | 1.492 | 0.098 | 0.000 | Naive GLM |
| Temperature_stand | -0.300 | 0.032 | 0.000 | Naive GLM |
| Rainfall_stand | -2.358 | 0.355 | 0.000 | Naive GLM |
| (Intercept) | 1.717 | 0.210 | 0.000 | GLS AR1 |
| Temperature_stand | -0.194 | 0.099 | 0.054 | GLS AR1 |
| Rainfall_stand | -0.097 | 0.064 | 0.134 | GLS AR1 |
| (Intercept) | 0.659 | 0.239 | 0.006 | Tscount |
| beta_1 | 0.511 | 0.116 | 0.000 | Tscount |
| Temperature_stand | -0.165 | 0.099 | 0.095 | Tscount |
| Rainfall_stand | -1.463 | 0.422 | 0.001 | Tscount |
| sigmasq | 0.544 | NA | NA | Tscount |
rbind(naive_glm_df,modelGLSAR.df,glm_tscount_df)%>%
ggplot(.,aes(x=Parameter,y=Coefficient,group=Method,fill=Method,color=Method))+
geom_point(aes(fill=Method))+
geom_pointrange(aes(x=Parameter,ymin=Coefficient-SE,ymax=Coefficient+SE))+
ylim(-3,2)+theme_bw()+
labs(y="Estimated value")
## Warning: Removed 1 rows containing missing values (`geom_segment()`).
Comparing the three different models we reached very similar results. That is cool, because it supports that both parameters, rainfall and temperature are truly affecting the total surveyed condors along the year. Yet, some small pieces differ and might lead to different conclusions.
NOTICE!
Hey, it is pretty much my first blog post. It got quite long than I expect and I’m planning to come back to improve it in a near future. So, be tuned!
Meanwhile, what about following me on Twitter to check the next posts? @anycommomname
Any comments, feel free to be in touch. Leave a comment, use the twitter or send me a email
#if woundering why we must normalize the residuals please check here.
https://stats.stackexchange.com/questions/80823/do-autocorrelated-residual-patterns-remain-even-in-models-with-different%20residuals%20type%20normalized%20work%20in%20glm%20in%20R-corre↩︎