all-analyses.Rmd 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947
  1. ---
  2. title: Establishing the reliability and validity of measures extracted from long-form
  3. recordings
  4. output:
  5. pdf_document:
  6. toc: yes
  7. toc_depth: 3
  8. html_document:
  9. toc: yes
  10. toc_depth: '3'
  11. df_print: paged
  12. ---
  13. ```{r setup, include=FALSE}
  14. knitr::opts_chunk$set(echo = FALSE, warning = FALSE)
  15. library("lme4")
  16. library("performance") # ICC
  17. library(ggplot2)
  18. library(ggthemes)
  19. library(ggpubr)
  20. library(kableExtra)
  21. library(psych)
  22. library(dplyr)
  23. library(tidyr)
  24. cbPalette <- c("#999999", "#E69F00", "#56B4E9", "#009E73", "#F0E442", "#0072B2", "#D55E00", "#CC79A7")
  25. # List of corpora we are interested in
  26. corpora <- c('bergelson', 'lucid', 'winnipeg', 'warlaumont','cougar','fausey')
  27. # Columns that should not be scaled or taken into account as metrics
  28. no.scale.columns <- c('experiment', 'session_id', 'child_id','child_id_unique',
  29. 'date_iso', 'child_dob', 'missing_audio',"age_bin","duration","usession_id", "normative")
  30. data_sets = c('aclew', 'lena')
  31. ```
  32. ## TODO later
  33. - split cougar into normative and not (Done, to be checked by @alex though)
  34. - consistency within files by comparing even versus odd hours of the day
  35. - extract SD, median & IQR per hour and perhaps something that gives an idea of peak activity -- eg peak N & dur per hour
  36. ## TO think
  37. - factor analyses: first attempt done, but am I confused about how to do it?
  38. - code for estimating CI for ICC -- looks like the only way is via bootstrapping, in which case,
  39. - leave for the end since it'll be a LONG time calculating [link](https://stats.stackexchange.com/questions/184767/how-do-i-calculate-the-confidence-interval-of-an-icc/564139#564139)
  40. ## Generate data
  41. By default, these chunks are not re-evaluated.
  42. ```{r icc-allcorporatogether, eval = FALSE}
  43. # Declare df to store ICCs
  44. df.icc.mixed.cols = c("data_set","metric", "iqr",
  45. "age_b","age_se","age_t",
  46. "icc_adjusted", "icc_conditional", "icc_child_id_corpus", "icc_corpus",
  47. "child_id_var","corpus_var","residual_var",
  48. "child_id_sd","corpus_sd","residual_sd",
  49. "nobs",
  50. "formula","sw")
  51. df.icc.mixed = data.frame(matrix(ncol=length(df.icc.mixed.cols),nrow=0, dimnames=list(NULL, df.icc.mixed.cols)),
  52. stringsAsFactors = FALSE)
  53. for (data_set in data_sets){ #data_set="aclew"
  54. # Load data and remove unwanted corpora
  55. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  56. mydat <- mydat[is.element(mydat$experiment, corpora),]
  57. all_cols = names(mydat)
  58. metrics = all_cols[!is.element(all_cols, no.scale.columns)]
  59. #remove outliers
  60. # WILLIAM: Why not use IQR to remove outliers?
  61. # .V1 ?
  62. for(metric in metrics) mydat[, metric] <- ifelse(scale(mydat[, metric])>2.5 | scale(mydat[, metric]) < -2.5,NA,mydat[, metric])
  63. colnames(mydat)<-gsub(".V1","", colnames(mydat),fixed=T)
  64. # Scale mydat
  65. mydat[, metrics] <- scale(mydat[, metrics])
  66. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  67. #print(summary(mydat)) #to look at distribution of mydat
  68. # Fit LMER
  69. for (metric in metrics){#metric="lp_n"
  70. # Formula = metric ~ age + (1|experiment/child_id)
  71. # = metric ~ age + (1|experiment) + (1|experiment:child_id)
  72. # age -> fixed effect
  73. # experiment -> random effect
  74. # child:experiment (child nested in experiment) -> random effect
  75. # AC double checked: this absolutely ensures no confusion bc child_id repeated across corpora (ie using / enforces nesting)
  76. formula <- as.formula(paste0(metric, "~ age + (1|experiment/child_id)"))
  77. model <- lmer(formula, data=mydat)
  78. form="full"
  79. # get IQR of metric
  80. iqr = quantile(mydat[,metric],.75,na.rm=T)-quantile(mydat[,metric],.25,na.rm=T)
  81. # Ran Ef
  82. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  83. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  84. if(isSingular(model)){
  85. #check if this is due to exp causing overfit
  86. if(round(ranefs_vars[2],3)==round(ranefs_stdv[2],3) & round(ranefs_vars[2],3)==0){
  87. formula <- as.formula(paste0(metric, "~ age + (1|child_id)"))
  88. model <- lmer(formula, data=mydat)
  89. form = "no_exp"
  90. }else{#otherwise, the problem is probably the child
  91. if(round(ranefs_vars[1],3)==round(ranefs_stdv[1],3) & round(ranefs_vars[1],3)==0){
  92. formula <- as.formula(paste0(metric, "~ age + (1|experiment)"))
  93. model <- lmer(formula, data=mydat)
  94. form = "no_chi"
  95. }
  96. }
  97. # re-extract Ran Ef when model changed
  98. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  99. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  100. }
  101. # print(paste(data_set,metric))
  102. # print(VarCorr(model))
  103. # Mixed ICC
  104. icc.result.mixed <- as.data.frame(icc(model))[-3]
  105. # By group ICC
  106. icc.result.split <- t(as.data.frame(icc(model, by_group=TRUE))$ICC)
  107. # print(paste(data_set,metric))
  108. # print(icc(model, by_group=TRUE))
  109. if(form =="no_exp"){
  110. icc.result.split = cbind(icc.result.split,NA)
  111. ranefs_vars = cbind(ranefs_vars[1],NA,ranefs_vars[2])
  112. ranefs_stdv = cbind(ranefs_stdv[1],NA,ranefs_stdv[2])
  113. }
  114. if(form =="no_chi"){
  115. icc.result.split = cbind(NA,icc.result.split)
  116. ranefs_vars = cbind(NA,ranefs_vars)
  117. ranefs_stdv = cbind(NA,ranefs_stdv)
  118. }
  119. sw=shapiro.test(resid(model))$p
  120. icc.row.mixed = cbind(data_set,
  121. metric,iqr,
  122. t(coefficients(summary(model))["age",]),
  123. icc.result.mixed,
  124. icc.result.split,
  125. ranefs_vars,
  126. ranefs_stdv,
  127. nobs(model),
  128. form,sw,
  129. stringsAsFactors=FALSE)
  130. df.icc.mixed[nrow(df.icc.mixed) + 1,] <- icc.row.mixed
  131. #print('-------------------')
  132. # insight get variance
  133. }
  134. }
  135. #df.icc.mixed
  136. write.csv(df.icc.mixed,"OUTPUT/df.icc.mixed.csv",row.names=F)
  137. ```
  138. ```{r icc-per-corpus, eval=FALSE}
  139. # repeat within each corpus
  140. df.icc.corpus.cols = c("data_set","corpus","metric", "iqr",
  141. "age_b","age_se","age_t",
  142. "icc_adjusted", "icc_conditional",
  143. "child_id_var","residual_var",
  144. "child_id_sd","residual_sd",
  145. "nobs",
  146. "formula","is.sing","sw")
  147. df.icc.corpus = data.frame(matrix(ncol=length(df.icc.corpus.cols),nrow=0, dimnames=list(NULL, df.icc.corpus.cols)),
  148. stringsAsFactors=FALSE)
  149. for (data_set in data_sets){ #data_set="aclew"
  150. # Load data and remove unwanted experiments
  151. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  152. for(corpus in corpora){#corpus="lucid"
  153. thiscordata <- mydat[mydat$experiment == corpus,]
  154. all_cols = names(thiscordata)
  155. metrics = all_cols[!is.element(all_cols, no.scale.columns)]
  156. #remove outliers
  157. for(metric in metrics) thiscordata[, metric] <- ifelse(scale(thiscordata[, metric])>2.5,NA,thiscordata[, metric])
  158. colnames(thiscordata)<-gsub(".V1","", colnames(thiscordata),fixed=T)
  159. # Scale thiscordata
  160. thiscordata[, metrics] <- scale(thiscordata[, metrics]) # TODO: check why this line fails for me (William)
  161. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  162. #print(summary(thiscordata)) #to look at distribution of thiscordata
  163. # Fit LMER
  164. for (metric in metrics) if(sum(!is.na(thiscordata[,metric]>30))){#metric="lp_n"
  165. formula <- as.formula(paste0(metric, "~ age + (1|child_id)"))
  166. model <- lmer(formula, data=thiscordata)
  167. form="full"
  168. # get IQR of metric
  169. iqr = quantile(thiscordata[,metric],.75,na.rm=T)-quantile(thiscordata[,metric],.25,na.rm=T)
  170. # Ran Ef
  171. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  172. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  173. # Mixed ICC
  174. if(!is.na(icc(model))) icc.result.mixed <- as.data.frame(icc(model))[-3] else icc.result.mixed <- cbind(NA,NA)
  175. sw=shapiro.test(resid(model))$p
  176. icc.row = cbind(data_set,corpus,
  177. metric,iqr,
  178. t(coefficients(summary(model))["age",]),
  179. icc.result.mixed,
  180. ranefs_vars,
  181. ranefs_stdv,
  182. nobs(model),
  183. form,isSingular(model),sw,
  184. stringsAsFactors=FALSE)
  185. df.icc.corpus[nrow(df.icc.corpus) + 1,] <- icc.row
  186. #print('-------------------')
  187. # insight get variance
  188. }
  189. }
  190. }
  191. write.csv(df.icc.corpus,"OUTPUT/df.icc.corpus.csv",row.names=F)
  192. ```
  193. ```{r icc-age, eval=FALSE}
  194. # repeat within age group bins
  195. df.icc.age.cols = c("data_set","age_bin","metric", "iqr",
  196. "age_b","age_se","age_t",
  197. "icc_adjusted", "icc_conditional",
  198. "icc_child_id_corpus", "icc_corpus",
  199. "child_id_var","corpus_var","residual_var",
  200. "child_id_sd","corpus_sd","residual_sd",
  201. "nobs", "nchi","ncor",
  202. "formula","is.sing","sw")
  203. df.icc.age = data.frame(matrix(ncol=length(df.icc.age.cols),nrow=0, dimnames=list(NULL, df.icc.age.cols)),
  204. stringsAsFactors=FALSE)
  205. for (data_set in data_sets){ #data_set="lena"
  206. # Load data and remove unwanted corpuss
  207. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  208. mydat <- mydat[is.element(mydat$experiment, corpora),]
  209. mydat$age_bin <- cut(mydat$age,c(0:20*6))
  210. for(thisage in levels(mydat$age_bin)){#age= "(0,6]"
  211. thiscordata <- mydat[mydat$age_bin == thisage,]
  212. if(dim(thiscordata)[1]>30){
  213. thiscordata$child_id<-factor(thiscordata$child_id)
  214. all_cols = names(thiscordata)
  215. metrics = all_cols[!is.element(all_cols, no.scale.columns)]
  216. #remove outliers
  217. for(metric in metrics) thiscordata[, metric] <- ifelse(scale(thiscordata[, metric])>2.5,NA,thiscordata[, metric])
  218. colnames(thiscordata)<-gsub(".V1","", colnames(thiscordata),fixed=T)
  219. # Scale thiscordata
  220. thiscordata[, metrics] <- scale(thiscordata[, metrics])
  221. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  222. #print(summary(thiscordata)) #to look at distribution of thiscordata
  223. # Fit LMER
  224. for (metric in metrics){#metric="lp_n"
  225. thiscordata_metric=thiscordata[!is.na(thiscordata[,metric]),]
  226. if(sum(!is.na(thiscordata_metric[,metric]))>30 & length(levels(factor(thiscordata_metric$experiment))) > 1 ){
  227. formula <- as.formula(paste0(metric, "~ age + (1|experiment/child_id)"))
  228. model <- lmer(formula, data=thiscordata_metric)
  229. form="full"
  230. # get IQR of metric
  231. iqr = quantile(thiscordata_metric[,metric],.75,na.rm=T)-quantile(thiscordata_metric[,metric],.25,na.rm=T)
  232. # Ran Ef
  233. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  234. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  235. if(isSingular(model)){
  236. #check if this is due to exp causing overfit
  237. if(ranefs_vars[2]==ranefs_stdv[2] & ranefs_vars[2]==0){
  238. formula <- as.formula(paste0(metric, "~ age + (1|child_id)"))
  239. model <- lmer(formula, data=mydat)
  240. form = "no_exp"
  241. }else{#otherwise, the problem is the child
  242. if(ranefs_vars[1]==ranefs_stdv[1] & ranefs_vars[1]==0){
  243. formula <- as.formula(paste0(metric, "~ age + (1|experiment)"))
  244. model <- lmer(formula, data=mydat)
  245. form = "no_chi"
  246. }
  247. }
  248. # re-extract Ran Ef when model changed
  249. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  250. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  251. }
  252. # print(paste(data_set,metric))
  253. # print(VarCorr(model))
  254. # Mixed ICC
  255. if(!isSingular(model)) icc.result.mixed <- as.data.frame(icc(model))[-3] else icc.result.mixed <- cbind(NA,NA)
  256. # By group ICC
  257. if(!isSingular(model)) icc.result.split <- t(as.data.frame(icc(model, by_group=TRUE))$ICC) else icc.result.split <- cbind(NA,NA)
  258. # print(paste(data_set,metric))
  259. # print(icc(model, by_group=TRUE))
  260. if(form =="no_exp"){
  261. icc.result.split = cbind(icc.result.split,NA)
  262. ranefs_vars = cbind(ranefs_vars[1],NA,ranefs_vars[2])
  263. ranefs_stdv = cbind(ranefs_stdv[1],NA,ranefs_stdv[2])
  264. }
  265. if(form =="no_chi"){
  266. icc.result.split = cbind(NA,icc.result.split)
  267. ranefs_vars = cbind(NA,ranefs_vars)
  268. ranefs_stdv = cbind(NA,ranefs_stdv)
  269. }
  270. sw=shapiro.test(resid(model))$p
  271. icc.row = cbind(data_set,thisage,
  272. metric,iqr,
  273. t(coefficients(summary(model))["age",]),
  274. icc.result.mixed,
  275. icc.result.split,
  276. ranefs_vars,
  277. ranefs_stdv,
  278. nobs(model),t(summary(model)$n),
  279. form,isSingular(model),sw,
  280. stringsAsFactors=FALSE)
  281. df.icc.age[nrow(df.icc.age) + 1,] <- icc.row
  282. #print('-------------------')
  283. # insight get variance
  284. }
  285. }
  286. }
  287. # else icc.row = cbind(data_set,thisage, NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
  288. # dim(thiscordata)[1],
  289. # NA,NA,NA)
  290. }
  291. }
  292. write.csv(df.icc.age,"OUTPUT/df.icc.age.csv",row.names=F)
  293. ```
  294. ```{r icc-normativity, eval=FALSE}
  295. corpus = c('cougar')
  296. # repeat within each corpus
  297. df.icc.normativity.cols = c("data_set","normative","metric", "iqr",
  298. "age_b","age_se","age_t",
  299. "icc_adjusted", "icc_conditional",
  300. "child_id_var","residual_var",
  301. "child_id_sd","residual_sd",
  302. "nobs",
  303. "formula","is.sing","sw")
  304. df.icc.normativity = data.frame(matrix(ncol=length(df.icc.normativity.cols),nrow=0, dimnames=list(NULL, df.icc.normativity.cols)),
  305. stringsAsFactors=FALSE)
  306. for (data_set in data_sets){ #data_set="aclew"
  307. print(data_set)
  308. # Load data and remove unwanted experiments
  309. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  310. corpus_data <- mydat[mydat$experiment == corpus,]
  311. children <- read.csv(paste0('DATA/', 'children.csv'))
  312. children <- children[, c('child_id', 'normative', 'experiment')]
  313. # Merge data and children normativity
  314. corpus_data <- merge(corpus_data, children, on=c('child_id', 'experiment'))
  315. normativity_items <- unique(corpus_data[, c('normative')]) # Should be Y/N
  316. all_cols = names(corpus_data)
  317. no.scale.columns.norm <- c(no.scale.columns, 'normative')
  318. metrics = all_cols[!is.element(all_cols, no.scale.columns.norm)]
  319. #remove outliers
  320. # for(metric in metrics) corpus_data[, metric] <- ifelse(scale(corpus_data[, metric])>2.5,NA,corpus_data[, metric])
  321. # colnames(corpus_data)<-gsub(".V1","", colnames(corpus_data),fixed=T)
  322. # Scale thiscordata
  323. # print(corpus_data)
  324. corpus_data[, metrics] <- scale(corpus_data[, metrics])
  325. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  326. #print(summary(thiscordata)) #to look at distribution of thiscordata
  327. # Fit LMER
  328. for (normativity in normativity_items)
  329. {
  330. thiscordata <- corpus_data[corpus_data$normative == normativity,]
  331. # Not sure why we get NAs for LENA data
  332. # TODO: check why we have NAs
  333. for (metric in metrics)if(sum(!is.na(thiscordata[,metric]>0))){#metric="lp_n"
  334. print(metric)
  335. formula <- as.formula(paste0(metric, "~ age + (1|child_id)"))
  336. model <- lmer(formula, data=thiscordata)
  337. form="full"
  338. # get IQR of metric
  339. iqr = quantile(thiscordata[,metric],.75,na.rm=T)-quantile(thiscordata[,metric],.25,na.rm=T)
  340. # Ran Ef
  341. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  342. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  343. # Mixed ICC
  344. if(!is.na(icc(model))) icc.result.mixed <- as.data.frame(icc(model))[-3] else icc.result.mixed <- cbind(NA,NA)
  345. sw=shapiro.test(resid(model))$p
  346. icc.row = cbind(data_set,normativity,
  347. metric,iqr,
  348. t(coefficients(summary(model))["age",]),
  349. icc.result.mixed,
  350. ranefs_vars,
  351. ranefs_stdv,
  352. nobs(model),
  353. form,isSingular(model),sw,
  354. stringsAsFactors=FALSE)
  355. df.icc.normativity[nrow(df.icc.normativity) + 1,] <- icc.row
  356. #print('-------------------')
  357. # insight get variance
  358. }
  359. }
  360. }
  361. write.csv(df.icc.normativity,"OUTPUT/df.icc.normativity.csv",row.names=F)
  362. ```
  363. ## Reliability analyses combining all corpora
  364. ```{r icc-allexp, echo=F,fig.width=4, fig.height=3,fig.cap="Distribution of ICC attributed to corpus (a) and children (b), when combining data from all corpora."}
  365. df.icc.mixed<-read.csv("OUTPUT/df.icc.mixed.csv")
  366. icc_exp <- ggplot(df.icc.mixed, aes(x = icc_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC corpus")+
  367. geom_jitter( aes(x = icc_corpus,y=0,colour=data_set))+ scale_fill_colorblind() +scale_colour_manual(values=cbPalette) + xlim(0,1)
  368. icc_chi <- ggplot(df.icc.mixed, aes(x = icc_child_id_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC child ID")+
  369. geom_jitter(aes(x = icc_child_id_corpus,y=0,colour=data_set))+ scale_fill_colorblind()+scale_colour_manual(values=cbPalette) + xlim(0,1)
  370. ggarrange(icc_exp, icc_chi,
  371. labels = c("A", "B"),
  372. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  373. ```
  374. ```{r worst, results="as.is"}
  375. x <- head(df.icc.mixed[order(df.icc.mixed$icc_child_id_corpus),c("data_set","metric","icc_child_id_corpus","icc_corpus")]) #worst
  376. kable(x,row.names = F,digits=2,caption="Measures with the lowest ICC attributed to children.")
  377. ```
  378. ```{r best, results="as.is"}
  379. x <- tail(df.icc.mixed[order(df.icc.mixed$icc_child_id_corpus),c("data_set","metric","icc_child_id_corpus","icc_corpus")]) #best
  380. kable(x,row.names = F,digits=2,caption="Measures with the highest ICC attributed to children.")
  381. ```
  382. ```{r sel, results="as.is"}
  383. x <- cbind(df.icc.mixed[df.icc.mixed$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.mixed$data_set=="lena",c("metric","icc_child_id_corpus")] ,
  384. df.icc.mixed[df.icc.mixed$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.mixed$data_set=="aclew",c("icc_child_id_corpus")]
  385. )
  386. kable(x,row.names = F,digits=2,caption="Most commonly used metrics.")
  387. ```
  388. ```{r icc-examples, echo=F,fig.width=4, fig.height=3,fig.cap="(A) scatterplot for one variable with relatively low ICCs versus (B) one with relatively higher ICCs (see Tables 1-2 for details)"}
  389. # figure of bad ICC: lena avg_voc_dur_chi; good ICC: lena voc_och_ph
  390. data_set="lena"
  391. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  392. mydat <- mydat[is.element(mydat$experiment, corpora),]
  393. #remove outliers
  394. for(metric in c("avg_voc_dur_chi","voc_och_ph")) mydat[, metric] <- ifelse(scale(mydat[, metric])>2.5 | scale(mydat[, metric]) < -2.5,NA,mydat[, metric])
  395. # remove those data points altogether
  396. mydat <- mydat[!is.na(mydat$avg_voc_dur_chi) & !is.na(mydat$voc_och_ph),]
  397. #make sure cols work as we want them to
  398. mydat$child_id <- paste(mydat$experiment,mydat$child_id)
  399. mydat$unique <- paste(mydat$experiment,mydat$child_id,mydat$session_id)
  400. #sample down to get 2 recs per child
  401. mysample = NULL
  402. for(thischild in levels(as.factor(mydat$child_id))){
  403. onechidat <- mydat[mydat$child_id == thischild,c("child_id","experiment","age","unique","avg_voc_dur_chi","voc_och_ph")]
  404. if(dim(onechidat)[1]>=2){
  405. selrows=sample(1:dim(onechidat)[1],2)
  406. mysample = rbind(mysample,
  407. cbind(onechidat[selrows[1],],
  408. onechidat[selrows[2],c("unique","avg_voc_dur_chi","voc_och_ph")]
  409. )
  410. )
  411. }
  412. }
  413. colnames(mysample)<-c("child_id","corpus","age","unique1","avg_voc_dur_chi1","voc_och_ph1","unique2","avg_voc_dur_chi2","voc_och_ph2")
  414. mysample$corpus=factor(mysample$corpus)
  415. bad <- ggplot(mysample, aes(avg_voc_dur_chi1,avg_voc_dur_chi2)) + geom_point(aes(colour = factor(corpus))) +
  416. geom_smooth(method='lm', formula= y~x)
  417. good <- ggplot(mysample, aes(voc_och_ph1,voc_och_ph2)) + geom_point(aes(colour = factor(corpus))) +
  418. geom_smooth(method='lm', formula= y~x)
  419. ggarrange(bad, good,
  420. labels = c("A", "B"),
  421. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  422. ```
  423. ## ICC normativity
  424. ```{r icc-normativity, echo=F,fig.width=4, fig.height=3,fig.cap="Distribution of ICC attributed to ACLEW (a) and LENA (b) in the Cougar corpus split by normativity."}
  425. df.icc.normativity<-read.csv("OUTPUT/df.icc.normativity.csv")
  426. icc_normative <- ggplot(df.icc.normativity[df.icc.normativity$data_set == 'aclew',], aes(x = icc_adjusted, fill = normative)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC ACLEW")+
  427. geom_jitter( aes(x = icc_adjusted,y=0,colour=normative))+ scale_fill_colorblind() +scale_colour_manual(values=cbPalette) + xlim(0,1)
  428. icc_non_normative <- ggplot(df.icc.normativity[df.icc.normativity$data_set == 'lena',], aes(x = icc_adjusted, fill = normative)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC LENA")+
  429. geom_jitter(aes(x = icc_adjusted,y=0,colour=normative))+ scale_fill_colorblind()+scale_colour_manual(values=cbPalette) + xlim(0,1)
  430. ggarrange(icc_normative, icc_non_normative,
  431. labels = c("A", "B"),
  432. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  433. ```
  434. ## Distance between recs
  435. ```{r count nb of recordings per child, warning=F, echo=FALSE}
  436. data_set="lena"
  437. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  438. mydat <- mydat[is.element(mydat$experiment, corpora),]
  439. mydat$usession_id <- paste(mydat$child_id,mydat$session_id)
  440. n_rec<-mydat %>%
  441. group_by(experiment, child_id)%>%
  442. summarise(n_rec=n())
  443. #hist(n_rec$n_rec)
  444. #sort(table(mydat$child_id))
  445. #summary(n_rec$n_rec)
  446. # n_rec %>%
  447. # group_by(experiment) %>%
  448. # summarise(temp = list(c(summary(object = n_rec)))) %>%
  449. # unnest_wider(temp)
  450. ggplot(n_rec, aes(n_rec))+
  451. geom_histogram(binwidth=1)+
  452. facet_wrap(~experiment, scales = "free_y")+
  453. ggtitle("distribution of # recordings per child, per corpus")
  454. ```
  455. ```{r max-dist}
  456. distance<-mydat %>%
  457. group_by(experiment, child_id)%>%
  458. summarise(distance = max(age)-min(age))
  459. # distance %>%
  460. # group_by(experiment) %>%
  461. # summarise(temp = list(c(summary(object = distance)))) %>%
  462. # unnest_wider(temp)
  463. ggplot(distance, aes(distance))+
  464. geom_histogram(binwidth=2)+
  465. facet_wrap(~experiment, scales = "free_y")+
  466. ggtitle("distance(mo) b/w first & last recording per corpus")
  467. ```
  468. ```{r count distance nearest recording, warning = F, echo=FALSE}
  469. dist_contig <- mydat %>%
  470. arrange(experiment, child_id, age) %>% #this sorts the table by corpus then id then age
  471. group_by(child_id) %>%
  472. mutate(n_rec = n(),
  473. age_dist_next_rec = lead(age) - age,
  474. #this gets the diff corresponding cell in the preceding row and a given row
  475. dist_max_min = max(age)-min(age)) %>% #this gets the max difference
  476. dplyr::select(experiment, child_id, age, usession_id,
  477. age_dist_next_rec, dist_max_min, n_rec) %>%
  478. filter(!is.na(age_dist_next_rec) & n_rec>0)
  479. # not all rec's have a next rec for same id, and not all have >1 rec per kid.
  480. # dist_contig %>%
  481. # group_by(experiment) %>%
  482. # summarise(temp = list(c(summary(object = age_dist_next_rec)))) %>%
  483. # unnest_wider(temp)
  484. ggplot(dist_contig, aes(age_dist_next_rec))+
  485. geom_histogram(binwidth=2)+
  486. facet_wrap(~experiment, scales = "free_y")+
  487. ggtitle("distance (mo) b/w contiguous recordings per corpus")
  488. dist_contig_pairs <- dist_contig %>%
  489. arrange(experiment, child_id, age,age_dist_next_rec) %>% #this sorts the table by corpus then id then age then dist
  490. group_by(child_id) %>%
  491. slice(c(1,2)) # take only one pair per child, minimizing distance -- this will tend to select the younger kids... need to think about a fix for that
  492. mydist <- dist_contig_pairs %>% slice(1)
  493. mydist <- subset(mydist, age_dist_next_rec<=2)
  494. ggplot(mydist, aes(age_dist_next_rec))+
  495. geom_histogram(binwidth=1)+
  496. facet_wrap(~experiment, scales = "free_y")+
  497. ggtitle("distribution of distance in the minimum distance paired recs, per corpus")
  498. ```
  499. ```{r icc-allcorporatogether_mindat, eval = FALSE}
  500. # Declare df to store ICCs
  501. df.icc.mixed.cols_mindist = c("data_set","metric", "iqr",
  502. "age_b","age_se","age_t",
  503. "icc_adjusted", "icc_conditional", "icc_child_id_corpus", "icc_corpus",
  504. "child_id_var","corpus_var","residual_var",
  505. "child_id_sd","corpus_sd","residual_sd",
  506. "nobs",
  507. "formula","sw")
  508. df.icc.mixed_mindist = data.frame(matrix(ncol=length(df.icc.mixed.cols_mindist),nrow=0, dimnames=list(NULL, df.icc.mixed.cols_mindist)))
  509. for (data_set in data_sets){ #data_set="aclew"
  510. # Load data and remove unwanted corpora
  511. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  512. mydat$usession_id <- paste(mydat$experiment,mydat$child_id,mydat$session_id)
  513. mydat <- mydat[is.element(mydat$experiment, corpora) & mydat$usession_id %in% levels(factor(dist_contig_pairs$usession_id)),] #this is the key condition: we only choose session id's from close recs
  514. all_cols = names(mydat)
  515. metrics = all_cols[!is.element(all_cols, no.scale.columns)]
  516. #remove outliers
  517. for(metric in metrics) mydat[, metric] <- ifelse(scale(mydat[, metric])>2.5 | scale(mydat[, metric]) < -2.5,NA,mydat[, metric])
  518. colnames(mydat)<-gsub(".V1","", colnames(mydat),fixed=T)
  519. # Scale mydat
  520. mydat[, metrics] <- scale(mydat[, metrics])
  521. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  522. #print(summary(mydat)) #to look at distribution of mydat
  523. # Fit LMER
  524. for (metric in metrics){#metric="lp_n"
  525. formula <- as.formula(paste0(metric, "~ age + (1|experiment/child_id)"))
  526. model <- lmer(formula, data=mydat)
  527. form="full"
  528. # get IQR of metric
  529. iqr = quantile(mydat[,metric],.75,na.rm=T)-quantile(mydat[,metric],.25,na.rm=T)
  530. # Ran Ef
  531. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  532. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  533. if(isSingular(model)){
  534. #check if this is due to exp causing overfit
  535. if(round(ranefs_vars[2],3)==round(ranefs_stdv[2],3) & round(ranefs_vars[2],3)==0){
  536. formula <- as.formula(paste0(metric, "~ age + (1|child_id)"))
  537. model <- lmer(formula, data=mydat)
  538. form = "no_exp"
  539. }else{#otherwise, the problem is probably the child
  540. if(round(ranefs_vars[1],3)==round(ranefs_stdv[1],3) & round(ranefs_vars[1],3)==0){
  541. formula <- as.formula(paste0(metric, "~ age + (1|experiment)"))
  542. model <- lmer(formula, data=mydat)
  543. form = "no_chi"
  544. }
  545. }
  546. # re-extract Ran Ef when model changed
  547. ranefs_vars <- t(as.data.frame(VarCorr(model))["vcov"])
  548. ranefs_stdv <- t(as.data.frame(VarCorr(model))["sdcor"])
  549. }
  550. # Mixed ICC
  551. icc.result.mixed <- as.data.frame(icc(model))[-3]
  552. # By group ICC
  553. icc.result.split <- t(as.data.frame(icc(model, by_group=TRUE))$ICC)
  554. if(form =="no_exp"){
  555. icc.result.split = cbind(icc.result.split,NA)
  556. ranefs_vars = cbind(ranefs_vars[1],NA,ranefs_vars[2])
  557. ranefs_stdv = cbind(ranefs_stdv[1],NA,ranefs_stdv[2])
  558. }
  559. if(form =="no_chi"){
  560. icc.result.split = cbind(NA,icc.result.split)
  561. ranefs_vars = cbind(NA,ranefs_vars)
  562. ranefs_stdv = cbind(NA,ranefs_stdv)
  563. }
  564. sw=shapiro.test(resid(model))$p
  565. icc.row.mixed = cbind(data_set,
  566. metric,iqr,
  567. t(coefficients(summary(model))["age",]),
  568. icc.result.mixed,
  569. icc.result.split,
  570. ranefs_vars,
  571. ranefs_stdv,
  572. nobs(model),
  573. form,sw)
  574. df.icc.mixed_mindist[nrow(df.icc.mixed_mindist) + 1,] <- icc.row.mixed
  575. #print('-------------------')
  576. # insight get variance
  577. }
  578. }
  579. #df.icc.mixed
  580. write.csv(df.icc.mixed_mindist,"OUTPUT/df.icc.mixed_mindist.csv",row.names=F)
  581. ```
  582. ```{r icc-allexp-mindist, echo=F,fig.width=4, fig.height=3,fig.cap="Distribution of ICC attributed to corpus (a) and children (b), when combining data from all corpora, but subsetting to two recs per child that have the minimum distance between them. See Tables 4-5 for best and worst metrics in these contiguous recordings."}
  583. df.icc.mixed<-read.csv("OUTPUT/df.icc.mixed_mindist.csv")
  584. icc_exp <- ggplot(df.icc.mixed, aes(x = icc_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC corpus")+
  585. geom_jitter(aes(x = icc_corpus,y=0,colour=data_set))+ scale_fill_colorblind() +scale_colour_manual(values=cbPalette)
  586. icc_chi <- ggplot(df.icc.mixed, aes(x = icc_child_id_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC child ID")+
  587. geom_jitter( aes(x = icc_child_id_corpus,y=0,colour=data_set))+ scale_fill_colorblind()+scale_colour_manual(values=cbPalette)
  588. ggarrange(icc_exp, icc_chi,
  589. labels = c("A", "B"),
  590. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  591. ```
  592. ```{r worst2, results="as.is"}
  593. x <- head(df.icc.mixed[order(df.icc.mixed$icc_child_id_corpus),c("data_set","metric","icc_child_id_corpus","icc_corpus")]) #worst
  594. kable(x,row.names = F,digits=2,caption="Measures with the lowest ICC attributed to children when subsetting to two recs per child that have the minimum distance between them.")
  595. ```
  596. ```{r best2, results="as.is"}
  597. x <- tail(df.icc.mixed[order(df.icc.mixed$icc_child_id_corpus),c("data_set","metric","icc_child_id_corpus","icc_corpus")]) #best
  598. kable(x,row.names = F,digits=2,caption="Measures with the highest ICC attributed to children when subsetting to two recs per child that have the minimum distance between them.")
  599. ```
  600. ```{r sel2, results="as.is"}
  601. x <- cbind(df.icc.mixed[df.icc.mixed$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.mixed$data_set=="lena",c("metric","icc_child_id_corpus")] ,
  602. df.icc.mixed[df.icc.mixed$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.mixed$data_set=="aclew",c("icc_child_id_corpus")]
  603. )
  604. kable(x,row.names = F,digits=2,caption="Most commonly used metrics when subsetting to two recs per child that have the minimum distance between them.")
  605. ```
  606. ## Reliability analyses per corpus
  607. ```{r icc-bycor, echo=F,fig.width=4, fig.height=10,fig.cap="Distribution of ICC attributed to children in each separate corpus."}
  608. df.icc.corpus<-read.csv("OUTPUT/df.icc.corpus.csv")
  609. ggplot(df.icc.corpus, aes(x = icc_adjusted, fill = data_set)) +
  610. geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +
  611. labs( x = "ICC child ID")+
  612. geom_jitter(aes(x = icc_adjusted,y=0,colour=data_set)) +
  613. facet_grid(rows=vars(corpus)) +
  614. scale_fill_colorblind()+scale_colour_manual(values=cbPalette)
  615. ```
  616. ## Reliability by child age
  617. ```{r relBYage, echo=F,fig.width=6, fig.height=10,fig.cap="Distribution of ICC attributed to corpus (a) and children (b), when binning children's age."}
  618. df.icc.age<-read.csv("OUTPUT/df.icc.age.csv")
  619. df.icc.age$age_bin<-factor(df.icc.age$age_bin,levels=c("(0,6]" , "(6,12]", "(12,18]" ,"(18,24]" ,"(24,30]", "(30,36]", "(36,42]", "(42,48]", "(48,54]" ))
  620. icc_exp <- ggplot(df.icc.age, aes(x = icc_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC corpus")+
  621. geom_jitter(aes(x = icc_corpus,y=0,colour=data_set))+
  622. facet_grid(rows=vars(age_bin)) +
  623. scale_fill_colorblind() +scale_colour_manual(values=cbPalette)
  624. icc_chi <- ggplot(df.icc.age, aes(x = icc_child_id_corpus, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "ICC child ID")+
  625. geom_jitter(aes(x = icc_child_id_corpus,y=0,colour=data_set))+
  626. facet_grid(rows=vars(age_bin)) +
  627. scale_fill_colorblind()+scale_colour_manual(values=cbPalette)
  628. ggarrange(icc_exp, icc_chi,
  629. labels = c("A", "B"),
  630. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  631. ```
  632. ```{r sel3, results="as.is"}
  633. # x <- cbind(df.icc.age[df.icc.age$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.age$data_set=="lena",c("metric","age_bin","icc_child_id_corpus")] ,
  634. # df.icc.age[df.icc.age$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.age$data_set=="aclew",c("metric","age_bin","icc_child_id_corpus")]
  635. # )
  636. kable(df.icc.age[df.icc.age$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.age$data_set=="lena",c("metric","age_bin","icc_child_id_corpus")],row.names = F,digits=2,caption="Most commonly used metrics by age bin (LENA).")
  637. kable(df.icc.age[df.icc.age$metric %in% c("voc_chi_ph","wc_adu_ph") & df.icc.age$data_set=="aclew",c("metric","age_bin","icc_child_id_corpus")],row.names = F,digits=2,caption="Most commonly used metrics by age bin (aclew).")
  638. write.csv(df.icc.age[df.icc.age$metric %in% c("voc_chi_ph","wc_adu_ph"),c("data_set","metric","age_bin","icc_child_id_corpus")],"tabXage.csv")
  639. ```
  640. ## Exploratory factor analysis
  641. ```{r}
  642. data_set="aclew" #focusing on ACLEW bc better results above
  643. mydat <- read.csv(paste0('DATA/', data_set,'_metrics.csv'))
  644. mydat <- mydat[is.element(mydat$experiment, corpora),]
  645. all_cols = names(mydat)
  646. metrics = all_cols[!is.element(all_cols, no.scale.columns)]
  647. #remove outliers
  648. for(metric in metrics) mydat[, metric] <- ifelse(scale(mydat[, metric])>2.5 | scale(mydat[, metric]) < -2.5,NA,mydat[, metric])
  649. colnames(mydat)<-gsub(".V1","", colnames(mydat),fixed=T)
  650. # Scale mydat
  651. mydat[, metrics] <- scale(mydat[, metrics])
  652. metrics = metrics[!(metrics=="age")] #remove age, since a regression with age twice doesn't make sense
  653. f1 <- psych::fa(mydat[, metrics])
  654. f1
  655. ```
  656. ## Validity against age
  657. ```{r ageFX, echo=F,fig.width=7, fig.height=10,fig.cap="Distribution of t for age when all corpora are analyzed together (a) or for each corpus separately (b)."}
  658. allcor <- ggplot(df.icc.mixed, aes(x = age_t, fill = data_set)) + geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +labs( x = "Age") +
  659. geom_jitter(aes(x = age_t,y=0,colour=data_set)) +
  660. scale_fill_colorblind() +scale_colour_manual(values=cbPalette)
  661. bycor <- ggplot(df.icc.corpus, aes(x = age_t, fill = data_set)) +
  662. geom_density(alpha = 0.5) + theme(legend.position = "top", axis.title.y=element_blank() ) +
  663. labs( x = "Age")+
  664. geom_jitter(aes(x = age_t,y=0,colour=data_set)) +
  665. facet_grid(rows=vars(corpus)) +
  666. scale_fill_colorblind()+scale_colour_manual(values=cbPalette)
  667. ggarrange(allcor, bycor,
  668. labels = c("A", "B"),
  669. ncol = 2, nrow = 1, common.legend = TRUE, vjust = 1.5)
  670. ```