About

R notebook for:

Init

options(
  digits = 3
)

library(pacman)
p_load(kirkegaard, rms, metafor, googlesheets4, metaviz)

theme_set(theme_bw())

Data

gs4_auth("the.dfx@gmail.com")
d = read_sheet("https://docs.google.com/spreadsheets/d/1tFr_ZAGz1gpEeCsFCJ6oRfiqwMP1z3ScGbVLYRFpWyQ/edit?ts=5f3339c5#gid=0") %>% 
  df_legalize_names()
## Reading from "A meta-analysis of ethnic Russian intelligence: tables"
## Range "Лист1"

Recode

#age function
estimate_age = function(x) {
  # browser()
  #find up to two numbers
  num_matches = str_match_all(x, "[\\d\\.]+")[[1]]
  
  #take mean
  return(num_matches %>% as.numeric() %>% mean(na.rm=T))
  
  #more? error
  stop("Unexpected data format", call. = F)
}

#derived data
d %<>% mutate(
  #fix score
  mean = Score %>% as.numeric(),
  mean_se = 15/sqrt(N),
  
  #fix reference
  Reference = str_replace(Reference, ",\\n", " "),
  
  #year
  year = str_match(Reference, "\\d+") %>% as.numeric(),
  
  #estimate mean age from age range
  mean_age = map_dbl(Age, estimate_age),
  
  #military or not
  military = Test == "Military test"
)

#manually code age for military men as 20
d$mean_age[d$Sample == "Young men, who want to serve in military"] = 20

#birth year
d$birth_year = d$year - d$mean_age

#sort by birth year
d %<>% arrange(birth_year)

Results

#main fit
main_meta = metafor::rma(yi = mean, sei = mean_se, data = d)
main_meta
## 
## Random-Effects Model (k = 83; tau^2 estimator: REML)
## 
## tau^2 (estimated amount of total heterogeneity): 9.7808 (SE = 1.5902)
## tau (square root of estimated tau^2 value):      3.1274
## I^2 (total heterogeneity / total variability):   99.13%
## H^2 (total variability / sampling variability):  114.60
## 
## Test for Heterogeneity:
## Q(df = 82) = 3233.1271, p-val < .0001
## 
## Model Results:
## 
## estimate      se      zval    pval    ci.lb     ci.ub 
##  99.4602  0.3510  283.3536  <.0001  98.7722  100.1482  *** 
## 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
plot(main_meta)

#forest plot
forest(main_meta)

#better forest plots
metaviz::viz_forest(main_meta,
                    xlab = "Mean IQ",
                    study_labels = d$Reference
                    )

GG_save("figs/forest.png")

metaviz::viz_forest(main_meta,
                    group = d$military %>% mapvalues(c(T, F), c("Military", "Non-military")),
                    col = d$military %>% mapvalues(c(T, F), c("red", "blue")),
                    summary_col = c("red", "blue"),
                    xlab = "Mean IQ",
                    study_labels = d$Reference,
                    variant = "thick"
                    )

GG_save("figs/forest_military.png")


#meta-regression
mod_meta = metafor::rma(yi = mean, sei = mean_se, mods =  ~ mean_age + birth_year + military, data = d)
mod_meta
## 
## Mixed-Effects Model (k = 83; tau^2 estimator: REML)
## 
## tau^2 (estimated amount of residual heterogeneity):     6.4249 (SE = 1.0763)
## tau (square root of estimated tau^2 value):             2.5347
## I^2 (residual heterogeneity / unaccounted variability): 98.72%
## H^2 (unaccounted variability / sampling variability):   77.94
## R^2 (amount of heterogeneity accounted for):            34.31%
## 
## Test for Residual Heterogeneity:
## QE(df = 79) = 2963.3538, p-val < .0001
## 
## Test of Moderators (coefficients 2:4):
## QM(df = 3) = 39.2132, p-val < .0001
## 
## Model Results:
## 
##                estimate       se     zval    pval      ci.lb     ci.ub 
## intrcpt       -117.0493  44.3300  -2.6404  0.0083  -203.9345  -30.1641   ** 
## mean_age         0.1390   0.0823   1.6894  0.0911    -0.0223    0.3003    . 
## birth_year       0.1069   0.0223   4.8027  <.0001     0.0633    0.1506  *** 
## militaryTRUE     0.6482   0.9739   0.6656  0.5057    -1.2606    2.5570      
## 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#plot fit
plot(mod_meta)

#plot birth year
ggplot(d, aes(birth_year, mean)) +
  geom_point() +
  geom_errorbar(aes(ymin = mean - 1.96*mean_se, ymax = mean + 1.96*mean_se)) +
  geom_smooth(method = lm) +
  scale_x_continuous("Birth year") +
  scale_y_continuous("Mean IQ")
## `geom_smooth()` using formula 'y ~ x'

GG_save("figs/birth_year_timeline.png")
## `geom_smooth()` using formula 'y ~ x'