I am new to R and statistics and am trying to do two-factor ANOVA on a dataset in csv file where values of each factor are in its own column. I was using
> mydata <- read.csv("myfile.csv")
> model = lm(result ~ factor1 * factor2, data=mydata)
As a check, I tried the ChickWeight data from R sample dataset.
> anova(with(ChickWeight, lm(weight ~ Time + Diet)))
Analysis of Variance Table
Response: weight
Df Sum Sq Mean Sq F value Pr(>F)
Time 1 2042344 2042344 1576.460 < 2.2e-16 ***
Diet 3 129876 43292 > 33.417 < 2.2e-16 ***
Residuals 573 742336 1296
> write.csv(file="ChickWeight.csv", x=ChickWeight, row.names=F)
> data = read.csv("ChickWeight.csv", header=T)
> anova(lm(weight ~ Time + Diet, data=data))
Analysis of Variance Table
Response: weight
Df Sum Sq Mean Sq F value Pr(>F)
Time 1 2042344 2042344 1537.033 < 2.2e-16 ***
Diet 1 108177 108177 81.412 < 2.2e-16 ***
Residuals 575 764036 1329
Noticeably, degrees of freedom are lost for Diet column with the data read from csv into a dataframe. What am I missing here?
Got the clue from this post: Why do R and statsmodels give slightly different ANOVA results?
When the data is being read from CSV file, the Diet column is becoming an ordinary numeric column, but for ANOVA it has to be a factor variable (I am still not clear why it is a separate class/kind in R and why it cannot take care of it automatically: inexact binary representation of floats? ).
So the solution was:
> data$Diet = factor(data$Diet)
> anova(lm("weight ~ Time + Diet", data=data))
Analysis of Variance Table
Response: weight
Df Sum Sq Mean Sq F value Pr(>F)
Time 1 2042344 2042344 1576.460 < 2.2e-16 ***
Diet 3 129876 43292 33.417 < 2.2e-16 ***
Residuals 573 742336 1296
Related
I am using ANOVA to analyse results from an experiment to see whether there are any effects of my explanatory variables (Heating and Dungfauna) on my response variable (Biomass). I started by looking at the main effects and interaction:
full.model <- lm(log(Biomass) ~ Heating*Dungfauna, data= df)
anova(full.model)
I understand that it is necessary to complete model simplification, removing non-significant interactions or effects to eventually reach the simplest model which still explains the results. I tried two ways of removing the interaction. However, when I manually remove the interaction (Heating*Fauna -> Heating+Fauna), the new ANOVA gives a different output to when I use this model simplification 'shortcut':
new.model <- update(full.model, .~. -Dungfauna:Heating)
anova(model)
Which way is the appropriate way to remove the interaction and simplify the model?
In both cases the data is log transformed -
lm(log(CC_noAcari_EmergencePatSoil)~ Dungfauna*Heating, data= biomass)
ANOVA output from manually changing Heating*Dungfauna to Heating+Dungfauna:
Response: log(CC_noAcari_EmergencePatSoil)
Df Sum Sq Mean Sq F value Pr(>F)
Heating 2 4.806 2.403 5.1799 0.01012 *
Dungfauna 1 37.734 37.734 81.3432 4.378e-11 ***
Residuals 39 18.091 0.464
ANOVA output from using simplification 'shortcut':
Response: log(CC_noAcari_EmergencePatSoil)
Df Sum Sq Mean Sq F value Pr(>F)
Dungfauna 1 41.790 41.790 90.0872 1.098e-11 ***
Heating 2 0.750 0.375 0.8079 0.4531
Residuals 39 18.091 0.464
R's anova and aov functions compute the Type I or "sequential" sums of squares. The order in which the predictors are specified matters. A model that specifies y ~ A + B is asking for the effect of A conditioned on B, whereas Y ~ B + A is asking for the effect of B conditioned on A. Notice that your first model specifies Dungfauna*Heating, while your comparison model uses Heating+Dungfauna.
Consider this simple example using the "mtcars" data set. Here I specify two additive models (no interactions). Both models specify the same predictors, but in different orders:
add.model <- lm(log(mpg) ~ vs + cyl, data = mtcars)
anova(add.model)
Df Sum Sq Mean Sq F value Pr(>F)
vs 1 1.22434 1.22434 48.272 1.229e-07 ***
cyl 1 0.78887 0.78887 31.103 5.112e-06 ***
Residuals 29 0.73553 0.02536
add.model2 <- lm(log(mpg) ~ cyl + vs, data = mtcars)
anova(add.model2)
Df Sum Sq Mean Sq F value Pr(>F)
cyl 1 2.00795 2.00795 79.1680 8.712e-10 ***
vs 1 0.00526 0.00526 0.2073 0.6523
Residuals 29 0.73553 0.02536
You could specify Type II or Type III sums of squares using car::Anova:
car::Anova(add.model, type = 2)
car::Anova(add.model2, type = 2)
Which gives the same result for both models:
Sum Sq Df F value Pr(>F)
vs 0.00526 1 0.2073 0.6523
cyl 0.78887 1 31.1029 5.112e-06 ***
Residuals 0.73553 29
summary also provides equivalent (and consistent) metrics regardless of the order of predictors, though it's not quite a formal ANOVA table:
summary(add.model)
Estimate Std. Error t value Pr(>|t|)
(Intercept) 3.92108 0.20714 18.930 < 2e-16 ***
vs -0.04414 0.09696 -0.455 0.652
cyl -0.15261 0.02736 -5.577 5.11e-06 ***
I have in the past had R perform aov's with interaction between two varbles, however I am unable to get it to do so now.
Code:
x.aov <- aov(thesis_temp$`Transformed Time to Metamorphosis` ~ thesis_temp$Sex + thesis_temp$Mature + thesis_temp$Sex * thesis_temp$Mature)
Output:
Df Sum Sq Mean Sq F value Pr(>F)
thesis_temp$Sex 1 0.000332 0.0003323 1.370 0.2452
thesis_temp$Mature 1 0.000801 0.0008005 3.301 0.0729 .
Residuals 82 0.019886 0.0002425
I want it to also include a Sex x Mature interaction, but it will not produce this. Any suggestions of how to get R to also do the interaction analysis?
I'd like to display significant stars in the result of Zelig regression with robust Standard Errors for tobit model.
Code is like this. But there are no significant stars, like normal tobit regression using AER package(tobit command)
library(Zelig)
# input
dat <- read.csv("http://www.omori.e.u-tokyo.ac.jp/STATA/Sample/select.csv")
head(dat)
# robust tobit
rb.tobit <- zelig(HOUR~CHILD+AGE+EDU+WAGE+HINC, below=0, above=Inf, model="tobit", data=dat, robust=T)
summary(rb.tobit)
Model:
Call:
z5$zelig(formula = HOUR ~ CHILD + AGE + EDU + WAGE + HINC, below = 0,
above = Inf, robust = T, data = dat)
Observations:
Total Left-censored Uncensored Right-censored
753 325 428 0
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1130.70774 443.05762 2.552 0.01071
CHILD -806.15058 245.32541 -3.286 0.00102
AGE -24.10593 7.68759 -3.136 0.00171
EDU 22.86477 31.14134 0.734 0.46281
WAGE 201.39910 34.23250 5.883 4.02e-09
HINC -53.92795 23.04316 -2.340 0.01927
Log(scale) 7.04989 0.04425 159.316 < 2e-16
Scale: 1153
Gaussian distribution
Number of Newton-Raphson Iterations: 4
Log-likelihood: -3812 on 7 Df
Wald-statistic: 75.14 on 5 Df, p-value: 8.6858e-15
Next step: Use 'setx' method
No stars in the right of the Coefficients.
Is there anyone know how to display significant stars?
even if it is a Little late:
-> type in: summary(rb.tobit, signif.stars=TRUE)
then it should work.
I'm trying to understand how to properly run an Repeated Measures or Nested ANOVA in R, without using mixed models. From consulting tutorials, the formula for a one-variable repeated measures anova is:
aov(Y ~ IV+ Error(SUBJECT/IV) )
where IV is the within subjects and subject is the identity of the subjects. However, most examples show outputs with two strata: Error:subject and Error: subject:WS. Meanwhile I am getting three strata ( Error:subject and Error: subject:WS, Error:within). Why do I have three strata, when I'm trying to specify only two (Within and Between)?
Here is an reproducible example:
data(beavers)
id = rep(c("beaver1","beaver2"),times=c(nrow(beaver1),nrow(beaver2)))
data = data.frame(id=id,rbind(beaver1,beaver2))
data$activ=factor(data$activ)
aov(temp~activ+Error(id/activ),data=data)
temp is a continuous measure of temperature, id is the identity of the beaver activ is binary factor for activity. The output of the model is:
Error: id
Df Sum Sq Mean Sq
activ 1 28.74 28.74
Error: id:activ
Df Sum Sq Mean Sq F value Pr(>F)
activ 1 15.313 15.313 18.51 0.145
Residuals 1 0.827 0.827
Error: Within
Df Sum Sq Mean Sq F value Pr(>F)
Residuals 210 7.85 0.03738
Using a small R sample dataset and the ANOVA example from statsmodels, the degrees of freedom for one of the variables are reported differently, & the F-values results are also slightly different. Perhaps they have slightly different default approaches? Can I set up statsmodels to use R's defaults?
import pandas as pd
import statsmodels.api as sm
from statsmodels.formula.api import ols
##R code on R sample dataset
#> anova(with(ChickWeight, lm(weight ~ Time + Diet)))
#Analysis of Variance Table
#
#Response: weight
# Df Sum Sq Mean Sq F value Pr(>F)
#Time 1 2042344 2042344 1576.460 < 2.2e-16 ***
#Diet 3 129876 43292 33.417 < 2.2e-16 ***
#Residuals 573 742336 1296
#write.csv(file='ChickWeight.csv', x=ChickWeight, row.names=F)
cw = pd.read_csv('ChickWeight.csv')
cw_lm=ols('weight ~ Time + Diet', data=cw).fit()
print(sm.stats.anova_lm(cw_lm, typ=2))
# sum_sq df F PR(>F)
#Time 2024187.608511 1 1523.368567 9.008821e-164
#Diet 108176.538530 1 81.411791 2.730843e-18
#Residual 764035.638024 575 NaN NaN
Head and tail of the datasets are the same*, also mean, min, max, median of weight and time.
Looks like "Diet" only has one degree of freedom in the statsmodels call which means it was probably treated as a continuous variable whereas in R it has 3 degrees of freedom so it probably was a factor/discrete random variable.
To make ols() treat "Diet" as a categorical random variable, use
cw_lm=ols('weight ~ C(Diet) + Time', data=cw).fit()