AI Experiment Analysis

Loading Libraries

library(afex) # to run the ANOVA and plot results
library(psych) # for the describe() command
library(ggplot2) # to visualize our results
library(expss) # for the cross_cases() command
library(car) # for the leveneTest() command
library(emmeans) # for posthoc tests
library(effsize) # for the cohen.d() command
library(apaTables) # to create our correlation table
library(kableExtra) # to create our correlation table
library(sjPlot) # to visualize our results
library(ggbeeswarm)

Importing Data

# import your AI results dataset
d <- read.csv(file="Data/Final Results.csv", header=T)

State Your Hypotheses & Chosen Tests

Check Your Variables

This is just basic variable checking that is used across all HW assignments.

# to view stats for all variables
describe(d)
           vars   n  mean    sd median trimmed   mad  min max range  skew
id            1 100 50.50 29.01   50.5   50.50 37.06  1.0 100  99.0  0.00
identity*     2 100 50.50 29.01   50.5   50.50 37.06  1.0 100  99.0  0.00
consent*      3 100  3.52  0.77    4.0    3.69  0.00  1.0   4   3.0 -1.70
age           4 100 37.85 11.71   36.0   37.51 16.31 18.0  60  42.0  0.22
race          5 100  6.00  0.00    6.0    6.00  0.00  6.0   6   0.0   NaN
gender        6 100  1.47  0.50    1.0    1.46  0.00  1.0   2   1.0  0.12
manip_out*    7 100 50.50 29.01   50.5   50.50 37.06  1.0 100  99.0  0.00
survey1       8 100  3.38  0.29    3.5    3.40  0.00  2.5   4   1.5 -0.80
ai_manip*     9 100 50.50 29.01   50.5   50.50 37.06  1.0 100  99.0  0.00
Condition    10 100  1.50  0.50    1.5    1.50  0.74  1.0   2   1.0  0.00
           kurtosis   se
id            -1.24 2.90
identity*     -1.24 2.90
consent*       2.45 0.08
age           -1.18 1.17
race            NaN 0.00
gender        -2.01 0.05
manip_out*    -1.24 2.90
survey1        0.90 0.03
ai_manip*     -1.24 2.90
Condition     -2.02 0.05
# we'll use the describeBy() command to view skew and kurtosis across our IVs
describeBy(d, group = d$Condition)

 Descriptive statistics by group 
group: 1
          vars  n  mean    sd median trimmed   mad  min   max range  skew
id           1 50 25.50 14.58   25.5   25.50 18.53  1.0  50.0    49  0.00
identity     2 50 49.22 29.90   45.0   49.05 37.81  1.0  98.0    97  0.03
consent      3 50  3.36  0.88    4.0    3.52  0.00  1.0   4.0     3 -1.28
age          4 50 36.22 11.83   35.5   35.98 15.57 18.0  57.0    39  0.18
race         5 50  6.00  0.00    6.0    6.00  0.00  6.0   6.0     0   NaN
gender       6 50  1.48  0.50    1.0    1.48  0.00  1.0   2.0     1  0.08
manip_out    7 50 53.12 24.25   57.5   53.02 20.76 13.0 100.0    87 -0.20
survey1      8 50  3.36  0.26    3.5    3.41  0.00  2.5   3.5     1 -1.61
ai_manip     9 50 55.40 27.73   60.5   56.83 25.95  2.0  99.0    97 -0.46
Condition   10 50  1.00  0.00    1.0    1.00  0.00  1.0   1.0     0   NaN
          kurtosis   se
id           -1.27 2.06
identity     -1.38 4.23
consent       0.81 0.12
age          -1.36 1.67
race           NaN 0.00
gender       -2.03 0.07
manip_out    -0.99 3.43
survey1       1.57 0.04
ai_manip     -0.98 3.92
Condition      NaN 0.00
------------------------------------------------------------ 
group: 2
          vars  n  mean    sd median trimmed   mad  min max range  skew
id           1 50 75.50 14.58   75.5   75.50 18.53 51.0 100  49.0  0.00
identity     2 50 51.78 28.34   52.0   51.85 36.32  3.0 100  97.0 -0.02
consent      3 50  3.68  0.62    4.0    3.80  0.00  1.0   4   3.0 -2.19
age          4 50 39.48 11.49   37.0   39.02 14.08 20.0  60  40.0  0.28
race         5 50  6.00  0.00    6.0    6.00  0.00  6.0   6   0.0   NaN
gender       6 50  1.46  0.50    1.0    1.45  0.00  1.0   2   1.0  0.16
manip_out    7 50 47.88 33.14   39.5   47.48 47.44  1.0  98  97.0  0.19
survey1      8 50  3.40  0.31    3.5    3.39  0.00  2.5   4   1.5 -0.37
ai_manip     9 50 45.60 29.70   38.5   44.25 27.43  1.0 100  99.0  0.44
Condition   10 50  2.00  0.00    2.0    2.00  0.00  2.0   2   0.0   NaN
          kurtosis   se
id           -1.27 2.06
identity     -1.15 4.01
consent       5.39 0.09
age          -1.20 1.62
race           NaN 0.00
gender       -2.01 0.07
manip_out    -1.48 4.69
survey1       0.16 0.04
ai_manip     -1.09 4.20
Condition      NaN 0.00
# also use histograms and scatterplots to examine your continuous variables
hist(d$survey1)

hist(d$age)

# and table() and cross_cases() to examine your categorical variables
# you may not need the cross_cases code
table(d$Condition)

 1  2 
50 50 

Check Your Assumptions

t-Test Assumptions

  • Data values must be independent (independent t-test only) (confirmed by data report)
  • Data obtained via a random sample (confirmed by data report)
  • IV must have two levels (will check below)
  • Dependent variable must be normally distributed (will check below. if issues, note and proceed)
  • Variances of the two groups must be approximately equal, aka ‘homogeneity of variance’. Lacking this makes our results inaccurate (will check below - this really only applies to Student’s t-test, but we’ll check it anyway)

Checking IV levels

# preview the levels and counts for your IV
table(d$Condition, useNA = "always")

   1    2 <NA> 
  50   50    0 
# note that the table() output shows you exactly how the levels of your variable are written. when recoding, make sure you are spelling them exactly as they appear

# check your variable types
str(d)
'data.frame':   100 obs. of  10 variables:
 $ id       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ identity : chr  "At 54, I’m a woman named Linda, juggling my career as a nonprofit director while grappling with feelings of lon"| __truncated__ "I’m 28, an aspiring graphic designer in Seattle, feeling stressed under the weight of student loans and living "| __truncated__ "I'm a 40-year-old woman named Sarah, a marketing manager living in Minneapolis. I thrive in my career but often"| __truncated__ "I’m a 25-year-old man, navigating the complexities of my career as a graphic designer. While I love creating, I"| __truncated__ ...
 $ consent  : chr  "I understand these instructions." "I understand these instructions." "I understand these instructions." "I understand these instructions." ...
 $ age      : int  54 28 40 25 25 52 50 37 19 43 ...
 $ race     : int  6 6 6 6 6 6 6 6 6 6 ...
 $ gender   : int  2 2 2 1 2 2 2 1 1 1 ...
 $ manip_out: chr  "Over the past month, I committed to practicing yoga three times a week for twenty minutes each session. I set a"| __truncated__ "After practicing yoga three times a week for twenty minutes over the last month, I noticed several changes. Ini"| __truncated__ "After one month of practicing yoga three times per week for twenty minutes, I feel a noticeable shift in my ove"| __truncated__ "After a month of practicing yoga three times a week for twenty minutes, I noticed several changes in my daily l"| __truncated__ ...
 $ survey1  : num  3.5 3.5 3 3 3.5 3.5 3.5 3 3.4 3.5 ...
 $ ai_manip : chr  "I answered the questions based on my experiences with yoga as a mindfulness practice, which helped me manage fe"| __truncated__ "I answered based on my experiences with yoga and mindfulness over the past month. I aimed to reflect how these "| __truncated__ "I answered the questions based on my transformative experience with yoga, which significantly reduced my anxiet"| __truncated__ "I responded as I did because practicing yoga helped me find balance in my life as a graphic designer, reducing "| __truncated__ ...
 $ Condition: int  1 1 1 1 1 1 1 1 1 1 ...
# make sure that your IV is recognized as a factor by R
# if you created a new _rc variable make sure to use that one instead
d$Condition <- as.factor(d$Condition)

Testing Homogeneity of Variance with Levene’s Test

We can test whether the variances of our two groups are equal using Levene’s test. The null hypothesis is that the variance between the two groups is equal, which is the result we want. So when running Levene’s test we’re hoping for a non-significant result!

# use the leveneTest() command from the car package to test homogeneity of variance
# uses the same 'formula' setup that we'll use for our t-test: formula is y~x, where y is our DV and x is our IV
leveneTest(survey1~Condition, data = d)
Levene's Test for Homogeneity of Variance (center = median)
      Df F value Pr(>F)
group  1  1.1448 0.2873
      98               

ANOVA Assumptions

  • DV should be normally distributed across levels of the IV
  • All levels of the IVs should have equal number of cases and there should be no empty cells. Cells with low numbers decrease the power of the test (increase change of Type II error)
  • Homogeneity of variance should be assured
  • Outliers should be identified and removed
  • If you have confirmed everything about, the sampling distribution should be normal. (For a demonstration of what the sampling distribution is, go here.)

Check levels of IVs and combine/drop if needed

# preview the levels and counts for your IV
table(d$age, useNA = "always")

  18   19   20   21   22   24   25   27   28   29   30   31   32   33   34   35 
   1    1    3    1    2    4    8    3    5    5    3    1    1    3    2    3 
  36   37   38   39   40   41   43   44   47   48   49   50   51   52   53   54 
   5    2    1    4    3    4    2    1    3    5    2    3    3    3    1    1 
  55   56   57   59   60 <NA> 
   3    2    2    2    2    0 
# note that the table() output shows you exactly how the levels of your variable are written. when recoding, make sure you are spelling them exactly as they appear

# to combine levels
# this says that where any participant is coded as 'BAD' it should be replaced by 'GOOD'
d$age_rc[d$age == "18"] <- "emerging"
d$age_rc[d$age == "19"] <- "emerging"
d$age_rc[d$age == "20"] <- "emerging"
d$age_rc[d$age == "21"] <- "emerging"
d$age_rc[d$age == "22"] <- "emerging"
d$age_rc[d$age == "23"] <- "emerging"
d$age_rc[d$age == "24"] <- "emerging"
d$age_rc[d$age == "25"] <- "emerging"
d$age_rc[d$age == "26"] <- "emerging"
d$age_rc[d$age == "27"] <- "emerging"
d$age_rc[d$age == "28"] <- "emerging"
d$age_rc[d$age == "29"] <- "emerging"
d$age_rc[d$age == "30"] <- "young"
d$age_rc[d$age == "31"] <- "young"
d$age_rc[d$age == "32"] <- "young"
d$age_rc[d$age == "33"] <- "young"
d$age_rc[d$age == "34"] <- "young"
d$age_rc[d$age == "35"] <- "young"
d$age_rc[d$age == "36"] <- "young"
d$age_rc[d$age == "37"] <- "young"
d$age_rc[d$age == "38"] <- "young"
d$age_rc[d$age == "39"] <- "young"
d$age_rc[d$age == "40"] <- "young"
d$age_rc[d$age == "41"] <- "young"
d$age_rc[d$age == "42"] <- "young"
d$age_rc[d$age == "43"] <- "young"
d$age_rc[d$age == "44"] <- "young"
d$age_rc[d$age == "45"] <- "young"
d$age_rc[d$age == "46"] <- "middle"
d$age_rc[d$age == "47"] <- "middle"
d$age_rc[d$age == "48"] <- "middle"
d$age_rc[d$age == "49"] <- "middle"
d$age_rc[d$age == "50"] <- "middle"
d$age_rc[d$age == "51"] <- "middle"
d$age_rc[d$age == "52"] <- "middle"
d$age_rc[d$age == "53"] <- "middle"
d$age_rc[d$age == "54"] <- "middle"
d$age_rc[d$age == "55"] <- "middle"
d$age_rc[d$age == "56"] <- "middle"
d$age_rc[d$age == "57"] <- "middle"
d$age_rc[d$age == "58"] <- "middle"
d$age_rc[d$age == "59"] <- "middle"
d$age_rc[d$age == "60"] <- "middle"

table(d$age_rc, useNA = "always")

emerging   middle    young     <NA> 
      33       32       35        0 
# check your variable types
str(d)
'data.frame':   100 obs. of  11 variables:
 $ id       : int  1 2 3 4 5 6 7 8 9 10 ...
 $ identity : chr  "At 54, I’m a woman named Linda, juggling my career as a nonprofit director while grappling with feelings of lon"| __truncated__ "I’m 28, an aspiring graphic designer in Seattle, feeling stressed under the weight of student loans and living "| __truncated__ "I'm a 40-year-old woman named Sarah, a marketing manager living in Minneapolis. I thrive in my career but often"| __truncated__ "I’m a 25-year-old man, navigating the complexities of my career as a graphic designer. While I love creating, I"| __truncated__ ...
 $ consent  : chr  "I understand these instructions." "I understand these instructions." "I understand these instructions." "I understand these instructions." ...
 $ age      : int  54 28 40 25 25 52 50 37 19 43 ...
 $ race     : int  6 6 6 6 6 6 6 6 6 6 ...
 $ gender   : int  2 2 2 1 2 2 2 1 1 1 ...
 $ manip_out: chr  "Over the past month, I committed to practicing yoga three times a week for twenty minutes each session. I set a"| __truncated__ "After practicing yoga three times a week for twenty minutes over the last month, I noticed several changes. Ini"| __truncated__ "After one month of practicing yoga three times per week for twenty minutes, I feel a noticeable shift in my ove"| __truncated__ "After a month of practicing yoga three times a week for twenty minutes, I noticed several changes in my daily l"| __truncated__ ...
 $ survey1  : num  3.5 3.5 3 3 3.5 3.5 3.5 3 3.4 3.5 ...
 $ ai_manip : chr  "I answered the questions based on my experiences with yoga as a mindfulness practice, which helped me manage fe"| __truncated__ "I answered based on my experiences with yoga and mindfulness over the past month. I aimed to reflect how these "| __truncated__ "I answered the questions based on my transformative experience with yoga, which significantly reduced my anxiet"| __truncated__ "I responded as I did because practicing yoga helped me find balance in my life as a graphic designer, reducing "| __truncated__ ...
 $ Condition: Factor w/ 2 levels "1","2": 1 1 1 1 1 1 1 1 1 1 ...
 $ age_rc   : chr  "middle" "emerging" "young" "emerging" ...
# make sure that your IV is recognized as a factor by R
# if you created a new _rc variable make sure to use that one instead
d$age_rc <- as.factor(d$age_rc)

Run a Multiple Linear Regression

To check the assumptions for an ANOVA, we run our regression and then check our diagnostic plots.

# use the lm() command to run the regression
# dependent/outcome variable on the left, independent/predictor variables on the right
reg_model <- lm(d$survey1 ~ d$age_rc, data = d)

Check for outliers using Cook’s distance and a Residuals vs Leverage plot

For your homework, you’ll simply need to generate these plots, assess Cook’s distance in your dataset, and then identify any potential cases that are prominent outliers. Since we have some cutoffs, that makes this process is a bit less subjective than some of the other assessments we’ve done here, which is a nice change!

# Cook's distance
plot(reg_model, 4)

# Residuals vs Leverage
plot(reg_model, 5)

Check homogeneity of variance in a Scale-Location plot

You can check out this page for some other examples of this type of plot. (Notice that the Scale-Location plot is the third in the grids.)

For your homework, you’ll simply need to generate this plot and talk about how your plot compares to the ones pictured. Is it closer to the ‘good’ plots or one of the ‘bad’ plots? Again, this is a judgement call! It’s okay if feel uncertain, and you won’t be penalized for that.

plot(reg_model, 3)

Run Your Analysis

Run a t-Test

# very simple! we specify the dataframe alongside the variables instead of having a separate argument for the dataframe like we did for leveneTest()
t_output <- t.test(d$survey1~d$Condition)

View Test Output

t_output

    Welch Two Sample t-test

data:  d$survey1 by d$Condition
t = -0.69346, df = 94.757, p-value = 0.4897
alternative hypothesis: true difference in means between group 1 and group 2 is not equal to 0
95 percent confidence interval:
 -0.15451653  0.07451653
sample estimates:
mean in group 1 mean in group 2 
          3.358           3.398 

Calculate Cohen’s d

# once again, we use our formula to calculate cohen's d
d_output <- cohen.d(d$survey1~d$Condition)

View Effect Size

  • Trivial: < .2
  • Small: between .2 and .5
  • Medium: between .5 and .8
  • Large: > .8
d_output

Cohen's d

d estimate: -0.1386921 (negligible)
95 percent confidence interval:
     lower      upper 
-0.5360624  0.2586783 

Run an ANOVA

aov_model <- aov_ez(data = d,
                    id = "id",
                    between = c("age_rc"),
                    dv = "survey1",
                    anova_table = list(es = "pes"))
Contrasts set to contr.sum for the following variables: age_rc
# 

View Output

Effect size cutoffs from Cohen (1988):

  • η2 = 0.01 indicates a small effect
  • η2 = 0.06 indicates a medium effect
  • η2 = 0.14 indicates a large effect
nice(aov_model)
Anova Table (Type 3 tests)

Response: survey1
  Effect    df  MSE    F  pes p.value
1 age_rc 2, 97 0.08 1.23 .025    .296
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '+' 0.1 ' ' 1
# 
# nice(aov_model2)

Visualize Results

afex_plot(aov_model, x = "age_rc")

# 

Run Posthoc Tests (One-Way)

Only run posthocs if the test is significant! E.g., only run the posthoc tests on gender if there is a main effect for gender.

# emmeans(aov_model, specs="IV1", adjust="tukey")
# pairs(emmeans(aov_model, specs="IV1", adjust="tukey"))

Write Up Results

t-Test

Write-up of your results goes here. Check past labs/HWs for template.

One-Way ANOVA

Write-up of your results goes here. Check past labs/HWs for template.

References

Cohen J. (1988). Statistical Power Analysis for the Behavioral Sciences. New York, NY: Routledge Academic.