<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pablo Bernabeu</title><link>https://pablobernabeu.github.io/categories/r/</link><description>Recent content in R on Pablo Bernabeu</description><generator>Hugo -- gohugo.io</generator><language>en-uk</language><copyright>Pablo Bernabeu, 2015—{year}. Licence: [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Email: pcbernabeu@gmail.com. Cookies only used by third-party systems such as [Disqus](https://help.disqus.com/en/articles/1717155-use-of-cookies).</copyright><lastBuildDate>Tue, 24 Mar 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://pablobernabeu.github.io/categories/r/index.xml" rel="self" type="application/rss+xml"/><item><title>You shall know a word by the company it keeps — so choose your prompts wisely</title><link>https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/</link><pubDate>Tue, 24 Mar 2026 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/htmltools-fill/fill.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/htmlwidgets/htmlwidgets.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/plotly-binding/plotly.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/typedarray/typedarray.min.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/jquery/jquery.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/crosstalk/css/crosstalk.min.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/crosstalk/js/crosstalk.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/plotly-htmlwidgets-css/plotly-htmlwidgets.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2026/you-shall-know-a-word-by-the-company-it-keeps/index.en_files/plotly-main/plotly-latest.min.js">&lt;/script>
&lt;style type="text/css">
.figure p.caption, figcaption {
text-align: left;
}
.figure {
max-width: 100%;
overflow-x: auto;
}
.html-widget {
max-width: 100%;
width: 100% !important;
height: auto !important;
aspect-ratio: 4 / 3;
}
@media (max-width: 767px) {
.html-widget {
aspect-ratio: 1 / 1;
}
}
&lt;/style>
&lt;script>
// Collapse code chunks by default in this post
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("details").forEach(function(d) {
d.open = false;
var s = d.querySelector("summary");
if (s) {
s.textContent = "Expand";
s.style.fontWeight = "bold";
s.style.fontSize = "103%";
s.style.color = "#379E8A";
}
});
});
&lt;/script>
&lt;p>In computational linguistics, word meanings are shaped by their contexts. As the British linguist John Rupert Firth put it in 1957, ‘You shall know a word by the company it keeps’ (see &lt;a href="https://doi.org/10.18653/v1/2022.naacl-main.327">Brunila &amp;amp; LaViolette, 2022&lt;/a>, for a re-examination of the intellectual history). It sounds almost like life advice, but Firth meant something technical: words that habitually appear alongside each other tend to share semantic territory. The adjective ‘good’, for instance, is far more likely to appear near ‘kind’, ‘genuine’, ‘fair’ and ‘quality’ than near ‘broken’ or ‘fraud’ – and a model that tracks those neighbours can learn what ‘good’ means without ever being told. The principle extends to polysemy: ‘bank’ means something entirely different in the company of ‘river’ and ‘fishing rod’ than in the company of ‘loan’ and ‘account’. Context is everything.&lt;/p>
&lt;p>This deceptively simple insight is the bedrock on which generative AI was built. The earliest computational implementations of Firth’s principle, distributional semantic models such as Latent Semantic Analysis (LSA; &lt;a href="https://doi.org/10.1037/0033-295X.104.2.211">Landauer &amp;amp; Dumais, 1997&lt;/a>) and the Hyperspace Analogue to Language (&lt;a href="https://doi.org/10.3758/BF03204766">Lund &amp;amp; Burgess, 1996&lt;/a>), were modest by today’s standards: a matrix of word co-occurrence counts, a few hundred latent dimensions and a vocabulary of perhaps tens of thousands of words. Yet even these pocket-sized models captured real-world structure with startling fidelity. &lt;a href="https://doi.org/10.1111/j.1551-6709.2008.01003.x">Louwerse and Zwaan (2009)&lt;/a> showed that the frequency with which city names co-occur in English text predicts their actual geographical distances: cities close together on a map tend to be mentioned together more often, and an LSA model trained on text alone can reconstruct approximate maps of the United States without ever seeing one.&lt;/p>
&lt;p>Distributional models can also track sensorimotor properties of concepts (&lt;a href="https://doi.org/10.17635/lancaster/thesis/1795">Bernabeu, 2022&lt;/a>; &lt;a href="https://doi.org/10.1111/j.1756-8765.2010.01106.x">Louwerse, 2011&lt;/a>; &lt;a href="https://doi.org/10.1111/j.1551-6709.2010.01157.x">Louwerse &amp;amp; Connell, 2011&lt;/a>), though unaided text captures only part of the picture – grounding sensorimotor features more fully may require fine-tuning on human ratings (&lt;a href="https://doi.org/10.48550/arXiv.2603.03313">Wu et al., 2026&lt;/a>) or other forms of supervision (&lt;a href="https://doi.org/10.1038/s41562-025-02203-8">Xu et al., 2025&lt;/a>). Language, then, does not merely label the world – it encodes its structure, and even a simple co-occurrence model can read much of that encoding back.&lt;/p>
&lt;p>We can see this for ourselves. The R code included below (click ‘Expand’ to view it) applies LSA – one of the simplest distributional models – to three text collections, projects the resulting word vectors into two dimensions via PCA (principal component analysis) and plots them. In brief, LSA builds a &lt;em>term-document matrix&lt;/em> (a large table recording how often each word appears in each document), weights it with TF-IDF (term frequency–inverse document frequency, which highlights words distinctive to particular documents rather than ubiquitous everywhere) and then compresses it via &lt;em>truncated SVD&lt;/em> (singular value decomposition, a form of dimensionality reduction). Each corpus is split into two groups: the most &lt;em>distinctive&lt;/em> words per group (selected by the difference in mean TF-IDF weight between groups) are plotted in the group’s colour, while the most frequent &lt;em>shared&lt;/em> words appear in purple. Words that co-occur in similar contexts cluster together; words from different domains drift apart.&lt;/p>
&lt;p>PCA works by finding new axes, principal components, that capture the maximum variance in the data. Each word receives a &lt;em>loading&lt;/em> on each component: a number ranging from −1 to +1 that indicates how strongly that word contributes to that axis of variation (a gentle introduction to PCA in R is &lt;a href="https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r">available in an earlier post on this blog&lt;/a>). High absolute loadings on a component mean that the word is a strong marker of the distinction that component captures.&lt;/p>
&lt;p>How are the thematic groups decided? The code computes the mean TF-IDF weight of every word in each group of documents and then takes the difference. Words whose weight is much higher in group A than in group B are classified as distinctive to A, and vice versa. The top 15 words at each extreme become the coloured labels in the plot, while the most frequent words that do not belong to either extreme are labelled ‘Shared’. The grouping is therefore entirely data-driven: no human decides which words are ‘finance’ or ‘energy’ – the corpus statistics do. Above each plot, a table shows the mean loading of each thematic group on the first two principal components, with the highest positive loading per group highlighted in bold. A high absolute loading tells us that a given group of words is strongly aligned with that component; in other words, the component captures precisely the distinction between those groups. When one group loads heavily on PC1 while another does not, the first principal component is essentially the axis that separates them.&lt;/p>
&lt;div id="reuters-newswire-finance-vs-energy" class="section level3">
&lt;h3>Reuters Newswire: Finance vs Energy&lt;/h3>
&lt;p>The first corpus uses two classic newswire collections from the &lt;code>tm&lt;/code> package (&lt;a href="https://doi.org/10.18637/jss.v025.i05">Feinerer et al., 2008&lt;/a>): &lt;code>acq&lt;/code> (50 Reuters articles on corporate acquisitions) and &lt;code>crude&lt;/code> (20 articles on crude oil markets). Both have been standard NLP benchmarks since the 1980s (&lt;a href="http://kdd.ics.uci.edu/databases/reuters21578/reuters21578.html">Lewis, 1997&lt;/a>). The code builds a TF-IDF weighted term-document matrix, reduces it to a 20-dimensional LSA space via truncated SVD, and computes pairwise cosine similarities – a standard measure of how close two word vectors sit, on a scale from –1 (opposite) to +1 (identical) – using &lt;code>LSAfun::Cosine()&lt;/code> (&lt;a href="https://doi.org/10.3758/s13428-015-0662-x">Günther et al., 2016&lt;/a>). The PCA loadings table and word-vector plot below show the results.&lt;/p>
&lt;pre class="r">&lt;code>pkgs &amp;lt;- c(&amp;quot;LSAfun&amp;quot;, &amp;quot;tm&amp;quot;, &amp;quot;ggplot2&amp;quot;, &amp;quot;plotly&amp;quot;)
invisible(lapply(pkgs, function(p)
if (!requireNamespace(p, quietly = TRUE)) install.packages(p)))
library(LSAfun)
library(tm)
library(ggplot2)
library(plotly)
# --- Reusable helper: LSA + PCA plot ------------------------------------
# Builds a TF-IDF term-document matrix, computes a truncated SVD,
# selects the most distinctive and most shared words and projects them
# to 2D via PCA *on the selected words only* for maximum spread.
lsa_pipeline &amp;lt;- function(doc_list, labels, grp_a, grp_b,
lab_a, lab_b, colour_a, colour_b,
top_n = 15, n_shared = 10,
k = 20, min_docs = 4) {
corp &amp;lt;- VCorpus(VectorSource(doc_list))
corp &amp;lt;- tm_map(corp, content_transformer(tolower))
corp &amp;lt;- tm_map(corp, removePunctuation)
corp &amp;lt;- tm_map(corp, removeNumbers)
corp &amp;lt;- tm_map(corp, removeWords, stopwords(&amp;quot;en&amp;quot;))
corp &amp;lt;- tm_map(corp, stripWhitespace)
tdm &amp;lt;- as.matrix(TermDocumentMatrix(corp,
control = list(weighting = weightTfIdf,
bounds = list(global = c(min_docs, Inf)))))
k_use &amp;lt;- min(as.integer(k), nrow(tdm) - 1L, ncol(tdm) - 1L)
sv &amp;lt;- svd(tdm, nu = k_use, nv = k_use)
wlsa &amp;lt;- sv$u %*% diag(sv$d[1:k_use])
rownames(wlsa) &amp;lt;- rownames(tdm)
idx_a &amp;lt;- which(labels == grp_a)
idx_b &amp;lt;- which(labels == grp_b)
mean_a &amp;lt;- rowMeans(tdm[, idx_a, drop = FALSE])
mean_b &amp;lt;- rowMeans(tdm[, idx_b, drop = FALSE])
total &amp;lt;- mean_a + mean_b
spec &amp;lt;- mean_a - mean_b # positive = distinctive to A
top_a &amp;lt;- names(sort(spec, decreasing = TRUE))[1:top_n]
top_b &amp;lt;- names(sort(spec, decreasing = FALSE))[1:top_n]
shared_pool &amp;lt;- setdiff(names(sort(total, decreasing = TRUE)),
c(top_a, top_b))
shared &amp;lt;- head(shared_pool, n_shared)
hl &amp;lt;- unique(c(top_a, top_b, shared))
hl &amp;lt;- hl[hl %in% rownames(wlsa)]
# PCA on the selected words only, for better spatial spread
wlsa_hl &amp;lt;- wlsa[hl, , drop = FALSE]
pca &amp;lt;- prcomp(wlsa_hl, scale. = FALSE)
cd &amp;lt;- data.frame(PC1 = pca$x[, 1], PC2 = pca$x[, 2],
word = rownames(wlsa_hl))
cd$topic &amp;lt;- ifelse(cd$word %in% top_a &amp;amp; !cd$word %in% top_b, lab_a,
ifelse(cd$word %in% top_b &amp;amp; !cd$word %in% top_a, lab_b,
&amp;quot;Shared&amp;quot;))
p &amp;lt;- ggplot(cd, aes(PC1, PC2, colour = topic,
text = paste0(word, &amp;quot; (&amp;quot;, topic, &amp;quot;)&amp;quot;))) +
geom_point(size = 0, alpha = 0) +
scale_colour_manual(values = setNames(c(colour_a, colour_b, &amp;quot;#7B2D8E&amp;quot;),
c(lab_a, lab_b, &amp;quot;Shared&amp;quot;)),
guide = guide_legend(override.aes = list(size = 3, alpha = 1))) +
labs(x = &amp;quot;Principal Component 1&amp;quot;, y = &amp;quot;Principal Component 2&amp;quot;,
colour = NULL) +
theme_minimal(base_size = 12) +
theme(legend.position = &amp;quot;bottom&amp;quot;,
legend.margin = margin(t = -5),
axis.title.x = element_text(margin = margin(t = 12)),
axis.title.y = element_text(margin = margin(r = 12)),
plot.margin = margin(0, 0, 0, 0))
# Map each word to its group colour for label text
col_map &amp;lt;- setNames(c(colour_a, colour_b, &amp;quot;#7B2D8E&amp;quot;),
c(lab_a, lab_b, &amp;quot;Shared&amp;quot;))
cd$label_col &amp;lt;- col_map[cd$topic]
# Trim spatial outliers so the dense cluster is readable.
# Words beyond the IQR fence are dropped from the plot (not from LSA).
q1 &amp;lt;- quantile(cd$PC1, 0.25); q3 &amp;lt;- quantile(cd$PC1, 0.75)
iqr &amp;lt;- q3 - q1; fence &amp;lt;- 2.5
keep &amp;lt;- cd$PC1 &amp;gt;= (q1 - fence * iqr) &amp;amp; cd$PC1 &amp;lt;= (q3 + fence * iqr)
q1y &amp;lt;- quantile(cd$PC2, 0.25); q3y &amp;lt;- quantile(cd$PC2, 0.75)
iqry &amp;lt;- q3y - q1y
keep &amp;lt;- keep &amp;amp; cd$PC2 &amp;gt;= (q1y - fence * iqry) &amp;amp; cd$PC2 &amp;lt;= (q3y + fence * iqry)
cd &amp;lt;- cd[keep, , drop = FALSE]
pp &amp;lt;- ggplotly(p, tooltip = &amp;quot;text&amp;quot;)
# Hide all ggplot traces from plot AND legend
for (k in seq_along(pp$x$data)) {
pp$x$data[[k]]$marker$size &amp;lt;- 0.1
pp$x$data[[k]]$marker$opacity &amp;lt;- 0
pp$x$data[[k]]$showlegend &amp;lt;- FALSE
}
# Constrain axes to the data range (with a small pad)
pad_x &amp;lt;- diff(range(cd$PC1)) * 0.06
pad_y &amp;lt;- diff(range(cd$PC2)) * 0.06
# Add text traces per group (toggleable via legend)
legend_groups &amp;lt;- c(lab_a, lab_b, &amp;quot;Shared&amp;quot;)
legend_cols &amp;lt;- c(colour_a, colour_b, &amp;quot;#7B2D8E&amp;quot;)
offscreen_x &amp;lt;- max(cd$PC1) + pad_x * 50
offscreen_y &amp;lt;- max(cd$PC2) + pad_y * 50
for (i in seq_along(legend_groups)) {
grp &amp;lt;- legend_groups[i]
grp_data &amp;lt;- cd[cd$topic == grp, , drop = FALSE]
if (nrow(grp_data) == 0) next
# Text trace at actual positions (no legend entry)
pp &amp;lt;- pp %&amp;gt;% add_trace(
x = grp_data$PC1, y = grp_data$PC2,
type = &amp;quot;scatter&amp;quot;, mode = &amp;quot;text&amp;quot;,
text = grp_data$word,
textfont = list(size = 11, color = legend_cols[i]),
name = grp, legendgroup = grp, showlegend = FALSE,
hoverinfo = &amp;quot;text&amp;quot;,
hovertext = paste0(grp_data$word, &amp;quot; (&amp;quot;, grp, &amp;quot;)&amp;quot;),
inherit = FALSE
)
# Legend-only marker trace (off-screen, linked via legendgroup)
pp &amp;lt;- pp %&amp;gt;% add_trace(
x = offscreen_x, y = offscreen_y, type = &amp;quot;scatter&amp;quot;, mode = &amp;quot;markers&amp;quot;,
marker = list(size = 12, color = legend_cols[i], opacity = 1,
symbol = &amp;quot;circle&amp;quot;),
name = grp, legendgroup = grp, showlegend = TRUE,
hoverinfo = &amp;quot;skip&amp;quot;, inherit = FALSE
)
}
pp &amp;lt;- pp %&amp;gt;% layout(
legend = list(orientation = &amp;quot;h&amp;quot;, x = 0.5, xanchor = &amp;quot;center&amp;quot;,
y = -0.12, yanchor = &amp;quot;top&amp;quot;,
tracegroupgap = 2, itemwidth = 30,
itemsizing = &amp;quot;constant&amp;quot;,
font = list(size = 11),
bordercolor = &amp;quot;#CCCCCC&amp;quot;, borderwidth = 1,
bgcolor = &amp;quot;#FAFAFA&amp;quot;,
xpad = 4, ypad = 4),
xaxis = list(title = list(text = &amp;quot;Principal Component 1&amp;quot;,
standoff = 8),
range = c(min(cd$PC1) - pad_x, max(cd$PC1) + pad_x)),
yaxis = list(title = list(text = &amp;quot;Principal Component 2&amp;quot;,
standoff = 8),
range = c(min(cd$PC2) - pad_y, max(cd$PC2) + pad_y)),
margin = list(b = 55)
)
list(plot = pp, lsa = wlsa, tdm = tdm, pca = pca, words = cd)
}
# --- 1. Reuters newswire ------------------------------------------------
data(acq)
data(crude)
docs &amp;lt;- c(lapply(acq, content), lapply(crude, content))
labels &amp;lt;- c(rep(&amp;quot;acq&amp;quot;, length(acq)), rep(&amp;quot;crude&amp;quot;, length(crude)))
res1 &amp;lt;- lsa_pipeline(docs, labels,
grp_a = &amp;quot;acq&amp;quot;, grp_b = &amp;quot;crude&amp;quot;,
lab_a = &amp;quot;Finance&amp;quot;, lab_b = &amp;quot;Energy&amp;quot;,
colour_a = &amp;quot;#D55E00&amp;quot;, colour_b = &amp;quot;#0072B2&amp;quot;,
min_docs = 4)
# Cosine similarities in the 20-dimensional LSA space
pairs &amp;lt;- list(
c(&amp;quot;oil&amp;quot;, &amp;quot;barrel&amp;quot;), c(&amp;quot;shares&amp;quot;, &amp;quot;acquisition&amp;quot;),
c(&amp;quot;price&amp;quot;, &amp;quot;barrel&amp;quot;), c(&amp;quot;price&amp;quot;, &amp;quot;shares&amp;quot;),
c(&amp;quot;shares&amp;quot;, &amp;quot;oil&amp;quot;), c(&amp;quot;acquisition&amp;quot;, &amp;quot;barrel&amp;quot;))
pairs &amp;lt;- Filter(function(p) all(p %in% rownames(res1$lsa)), pairs)
sims &amp;lt;- sapply(pairs, function(p)
round(Cosine(p[1], p[2], tvectors = res1$lsa), 3))
names(sims) &amp;lt;- sapply(pairs, paste, collapse = &amp;quot; ~ &amp;quot;)
sims
#&amp;gt; oil ~ barrel shares ~ acquisition price ~ barrel
#&amp;gt; 0.675 0.236 0.938
#&amp;gt; price ~ shares shares ~ oil acquisition ~ barrel
#&amp;gt; 0.129 -0.014 -0.043&lt;/code>&lt;/pre>
&lt;table>
&lt;caption>&lt;span id="tab:loadings-reuters">Table 1: &lt;/span>&lt;em>Mean PCA Loadings on the First Two Components (Highest Positive Loading per Group in Bold, Excluding Shared)&lt;/em>&lt;/caption>
&lt;thead>
&lt;tr class="header">
&lt;th align="left">Group&lt;/th>
&lt;th align="right">PC1&lt;/th>
&lt;th align="right">PC2&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="left">Energy&lt;/td>
&lt;td align="right">&lt;strong>.439&lt;/strong>&lt;/td>
&lt;td align="right">-.321&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Finance&lt;/td>
&lt;td align="right">-.265&lt;/td>
&lt;td align="right">&lt;strong>.24&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Shared&lt;/td>
&lt;td align="right">.172&lt;/td>
&lt;td align="right">.069&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="figure" style="text-align: center">&lt;span style="display:block;" id="fig:plot-reuters">&lt;/span>
&lt;div class="plotly html-widget html-fill-item" id="htmlwidget-1" style="width:768px;height:576px;">&lt;/div>
&lt;script type="application/json" data-for="htmlwidget-1">{"x":{"data":[{"x":[0.28836086654331949,0.1657808941561569,0.24753346914792965,0.15005897875816435,0.098896621624986067,0.14711428780722954,0.17444498328263369,0.10607858018124708,0.08051017201028017,0.086010212199783401,0.064786099141849379,0.10008936204826478,0.07478606229021495,0.10014917224483195,0.063693207340012561],"y":[-0.24832225144148024,-0.17896550697907548,-0.15490496801074929,-0.1413326394049457,-0.095827323182578472,-0.16973391719486938,0.58180820005241962,-0.11247257380227436,-0.046945776019420869,0.19094653091790281,-0.057862022883080608,-0.10955960843206995,-0.05905400025962592,-0.097092739690789923,-0.047815628974686934],"text":["oil (Energy)","prices (Energy)","crude (Energy)","opec (Energy)","saudi (Energy)","posted (Energy)","january (Energy)","barrel (Energy)","bpd (Energy)","barrels (Energy)","kuwait (Energy)","brings (Energy)","last (Energy)","price (Energy)","official (Energy)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,114,178,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,114,178,1)"}},"hoveron":"points","name":"Energy","legendgroup":"Energy","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.049471990550235677,-0.12938039843126439,-0.04054852888666817,-0.49755766520957062,-0.029560512980131078,-0.23995081133082855,-0.40137146185349359,-0.62856787483224308,-0.12214171077436271,-0.019085633888122941,-0.030038900048657918,-0.078196579784648168,-0.015783548788308083,-0.14240672348438954,-0.021505496545829967],"y":[0.17489942694276914,0.060093524586883142,0.1041949847841091,-0.084375547690265146,0.13320400170100985,-0.00012950003840865457,-0.040846894528412295,-0.18311056236070655,0.0097847356884903595,0.091889478898152022,0.061464943402219266,0.10292251974440762,0.04075723759281874,0.021965967367350753,0.049873493966069916],"text":["shares (Finance)","inc (Finance)","stock (Finance)","undisclosed (Finance)","common (Finance)","corp (Finance)","terms (Finance)","division (Finance)","american (Finance)","offer (Finance)","systems (Finance)","merger (Finance)","company (Finance)","purchase (Finance)","acquire (Finance)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(213,94,0,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(213,94,0,1)"}},"hoveron":"points","name":"Finance","legendgroup":"Finance","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.014353753633487835,0.0031696540302367932,0.18245817839139369,0.089094799129091809,0.083143851465848101,0.052368314320282293,0.027273491858881414,-0.007611952348244886,0.0092360271773049563,0.072496258220543938],"y":[0.11100612457286085,0.012538616626605862,-0.084348513417700846,0.29552983519442522,-0.071906345744260608,-0.042238035098445911,-0.0079807751232539113,0.002684444070366845,0.10176894169435273,-0.11250787752611267],"text":["mln (Shared)","dlrs (Shared)","west (Shared)","billion (Shared)","today (Shared)","market (Shared)","new (Shared)","will (Shared)","pct (Shared)","contract (Shared)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(123,45,142,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(123,45,142,1)"}},"hoveron":"points","name":"Shared","legendgroup":"Shared","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.049471990550235677,-0.12938039843126439,-0.04054852888666817,-0.029560512980131078,-0.23995081133082855,-0.12214171077436271,-0.019085633888122941,-0.030038900048657918,-0.078196579784648168,-0.015783548788308083,-0.14240672348438954,-0.021505496545829967],"y":[0.17489942694276914,0.060093524586883142,0.1041949847841091,0.13320400170100985,-0.00012950003840865457,0.0097847356884903595,0.091889478898152022,0.061464943402219266,0.10292251974440762,0.04075723759281874,0.021965967367350753,0.049873493966069916],"type":"scatter","mode":"text","text":["shares","inc","stock","common","corp","american","offer","systems","merger","company","purchase","acquire"],"textfont":{"size":11,"color":"#D55E00"},"name":"Finance","legendgroup":"Finance","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["shares (Finance)","inc (Finance)","stock (Finance)","common (Finance)","corp (Finance)","american (Finance)","offer (Finance)","systems (Finance)","merger (Finance)","company (Finance)","purchase (Finance)","acquire (Finance)"],"marker":{"color":"rgba(31,119,180,1)","line":{"color":"rgba(31,119,180,1)"}},"error_y":{"color":"rgba(31,119,180,1)"},"error_x":{"color":"rgba(31,119,180,1)"},"line":{"color":"rgba(31,119,180,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.8732959001657634],"y":[1.9270860951021413],"type":"scatter","mode":"markers","marker":{"color":"#D55E00","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(255,127,14,1)"}},"name":"Finance","legendgroup":"Finance","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(255,127,14,1)"},"error_x":{"color":"rgba(255,127,14,1)"},"line":{"color":"rgba(255,127,14,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.28836086654331949,0.1657808941561569,0.24753346914792965,0.15005897875816435,0.098896621624986067,0.14711428780722954,0.10607858018124708,0.08051017201028017,0.086010212199783401,0.064786099141849379,0.10008936204826478,0.07478606229021495,0.10014917224483195,0.063693207340012561],"y":[-0.24832225144148024,-0.17896550697907548,-0.15490496801074929,-0.1413326394049457,-0.095827323182578472,-0.16973391719486938,-0.11247257380227436,-0.046945776019420869,0.19094653091790281,-0.057862022883080608,-0.10955960843206995,-0.05905400025962592,-0.097092739690789923,-0.047815628974686934],"type":"scatter","mode":"text","text":["oil","prices","crude","opec","saudi","posted","barrel","bpd","barrels","kuwait","brings","last","price","official"],"textfont":{"size":11,"color":"#0072B2"},"name":"Energy","legendgroup":"Energy","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["oil (Energy)","prices (Energy)","crude (Energy)","opec (Energy)","saudi (Energy)","posted (Energy)","barrel (Energy)","bpd (Energy)","barrels (Energy)","kuwait (Energy)","brings (Energy)","last (Energy)","price (Energy)","official (Energy)"],"marker":{"color":"rgba(44,160,44,1)","line":{"color":"rgba(44,160,44,1)"}},"error_y":{"color":"rgba(44,160,44,1)"},"error_x":{"color":"rgba(44,160,44,1)"},"line":{"color":"rgba(44,160,44,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.8732959001657634],"y":[1.9270860951021413],"type":"scatter","mode":"markers","marker":{"color":"#0072B2","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(214,39,40,1)"}},"name":"Energy","legendgroup":"Energy","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(214,39,40,1)"},"error_x":{"color":"rgba(214,39,40,1)"},"line":{"color":"rgba(214,39,40,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[-0.014353753633487835,0.0031696540302367932,0.18245817839139369,0.089094799129091809,0.083143851465848101,0.052368314320282293,0.027273491858881414,-0.007611952348244886,0.0092360271773049563,0.072496258220543938],"y":[0.11100612457286085,0.012538616626605862,-0.084348513417700846,0.29552983519442522,-0.071906345744260608,-0.042238035098445911,-0.0079807751232539113,0.002684444070366845,0.10176894169435273,-0.11250787752611267],"type":"scatter","mode":"text","text":["mln","dlrs","west","billion","today","market","new","will","pct","contract"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text"],"hovertext":["mln (Shared)","dlrs (Shared)","west (Shared)","billion (Shared)","today (Shared)","market (Shared)","new (Shared)","will (Shared)","pct (Shared)","contract (Shared)"],"marker":{"color":"rgba(148,103,189,1)","line":{"color":"rgba(148,103,189,1)"}},"error_y":{"color":"rgba(148,103,189,1)"},"error_x":{"color":"rgba(148,103,189,1)"},"line":{"color":"rgba(148,103,189,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.8732959001657634],"y":[1.9270860951021413],"type":"scatter","mode":"markers","marker":{"color":"#7B2D8E","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(140,86,75,1)"}},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(140,86,75,1)"},"error_x":{"color":"rgba(140,86,75,1)"},"line":{"color":"rgba(140,86,75,1)"},"xaxis":"x","yaxis":"y","frame":null}],"layout":{"margin":{"t":16,"r":0,"b":55,"l":45.429638854296407},"paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-0.27164951200327742,0.32005956721576839],"tickmode":"array","ticktext":["-0.50","-0.25","0.00","0.25"],"tickvals":[-0.5,-0.25,0,0.25],"categoryorder":"array","categoryarray":["-0.50","-0.25","0.00","0.25"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"y","title":{"text":"Principal Component 1","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-0.28095337663963454,0.32816096039257953],"tickmode":"array","ticktext":["-0.2","0.0","0.2","0.4","0.6"],"tickvals":[-0.20000000000000001,0,0.20000000000000001,0.40000000000000002,0.60000000000000009],"categoryorder":"array","categoryarray":["-0.2","0.0","0.2","0.4","0.6"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"x","title":{"text":"Principal Component 2","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","layer":"below","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"#FAFAFA","bordercolor":"#CCCCCC","borderwidth":1,"font":{"color":"rgba(0,0,0,1)","family":"","size":11},"title":{"text":"","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243}},"orientation":"h","x":0.5,"xanchor":"center","y":-0.12,"yanchor":"top","tracegroupgap":2,"itemwidth":30,"itemsizing":"constant","xpad":4,"ypad":4},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"220ce5d140a":{"x":{},"y":{},"colour":{},"text":{},"type":"scatter"},"220ce5d140a.1":{"x":[-0.049471990550235677,-0.12938039843126439,-0.04054852888666817,-0.029560512980131078,-0.23995081133082855,-0.12214171077436271,-0.019085633888122941,-0.030038900048657918,-0.078196579784648168,-0.015783548788308083,-0.14240672348438954,-0.021505496545829967],"y":[0.17489942694276914,0.060093524586883142,0.1041949847841091,0.13320400170100985,-0.00012950003840865457,0.0097847356884903595,0.091889478898152022,0.061464943402219266,0.10292251974440762,0.04075723759281874,0.021965967367350753,0.049873493966069916],"type":"scatter","mode":"text","text":["shares","inc","stock","common","corp","american","offer","systems","merger","company","purchase","acquire"],"textfont":{"size":11,"color":"#D55E00"},"name":"Finance","legendgroup":"Finance","showlegend":false,"hoverinfo":"text","hovertext":["shares (Finance)","inc (Finance)","stock (Finance)","common (Finance)","corp (Finance)","american (Finance)","offer (Finance)","systems (Finance)","merger (Finance)","company (Finance)","purchase (Finance)","acquire (Finance)"],"inherit":false},"220ce5d140a.2":{"x":1.8732959001657634,"y":1.9270860951021413,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#D55E00","opacity":1,"symbol":"circle"},"name":"Finance","legendgroup":"Finance","showlegend":true,"hoverinfo":"skip","inherit":false},"220ce5d140a.3":{"x":[0.28836086654331949,0.1657808941561569,0.24753346914792965,0.15005897875816435,0.098896621624986067,0.14711428780722954,0.10607858018124708,0.08051017201028017,0.086010212199783401,0.064786099141849379,0.10008936204826478,0.07478606229021495,0.10014917224483195,0.063693207340012561],"y":[-0.24832225144148024,-0.17896550697907548,-0.15490496801074929,-0.1413326394049457,-0.095827323182578472,-0.16973391719486938,-0.11247257380227436,-0.046945776019420869,0.19094653091790281,-0.057862022883080608,-0.10955960843206995,-0.05905400025962592,-0.097092739690789923,-0.047815628974686934],"type":"scatter","mode":"text","text":["oil","prices","crude","opec","saudi","posted","barrel","bpd","barrels","kuwait","brings","last","price","official"],"textfont":{"size":11,"color":"#0072B2"},"name":"Energy","legendgroup":"Energy","showlegend":false,"hoverinfo":"text","hovertext":["oil (Energy)","prices (Energy)","crude (Energy)","opec (Energy)","saudi (Energy)","posted (Energy)","barrel (Energy)","bpd (Energy)","barrels (Energy)","kuwait (Energy)","brings (Energy)","last (Energy)","price (Energy)","official (Energy)"],"inherit":false},"220ce5d140a.4":{"x":1.8732959001657634,"y":1.9270860951021413,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#0072B2","opacity":1,"symbol":"circle"},"name":"Energy","legendgroup":"Energy","showlegend":true,"hoverinfo":"skip","inherit":false},"220ce5d140a.5":{"x":[-0.014353753633487835,0.0031696540302367932,0.18245817839139369,0.089094799129091809,0.083143851465848101,0.052368314320282293,0.027273491858881414,-0.007611952348244886,0.0092360271773049563,0.072496258220543938],"y":[0.11100612457286085,0.012538616626605862,-0.084348513417700846,0.29552983519442522,-0.071906345744260608,-0.042238035098445911,-0.0079807751232539113,0.002684444070366845,0.10176894169435273,-0.11250787752611267],"type":"scatter","mode":"text","text":["mln","dlrs","west","billion","today","market","new","will","pct","contract"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":"text","hovertext":["mln (Shared)","dlrs (Shared)","west (Shared)","billion (Shared)","today (Shared)","market (Shared)","new (Shared)","will (Shared)","pct (Shared)","contract (Shared)"],"inherit":false},"220ce5d140a.6":{"x":1.8732959001657634,"y":1.9270860951021413,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#7B2D8E","opacity":1,"symbol":"circle"},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","inherit":false}},"cur_data":"220ce5d140a","visdat":{"220ce5d140a":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":[]}&lt;/script>
&lt;p class="caption">
Figure 1: &lt;em>Word Vectors from Reuters Newswire Articles (Finance vs Energy) Projected to Two Dimensions via PCA on a 20-Dimensional LSA Space.&lt;/em> Finance terms (vermilion) cluster in a distinct region from energy terms (blue); shared vocabulary occupies intermediate positions. Select an area of the plot to zoom in; double-click to reset.
&lt;/p>
&lt;/div>
&lt;p>The cosine similarities confirm what Figure 1 shows geometrically. Within-domain pairs cluster tightly – &lt;code>oil ~ barrel&lt;/code> and &lt;code>price ~ barrel&lt;/code> have high positive cosines because these words habitually appear together in oil-market dispatches – while cross-domain pairs like &lt;code>shares ~ oil&lt;/code> and &lt;code>acquisition ~ barrel&lt;/code> sit near zero: they simply never keep each other’s company. Notice, too, that &lt;code>price ~ shares&lt;/code> is far lower than &lt;code>price ~ barrel&lt;/code>. The same word, ‘price’, lands in a different region of the space depending on the context in which it predominantly occurs. Firth’s principle, made numerical.&lt;/p>
&lt;/div>
&lt;div id="state-of-the-union-pre-war-vs-post-war" class="section level3">
&lt;h3>State of the Union: Pre-War vs Post-War&lt;/h3>
&lt;p>From newswire to politics. The &lt;code>sotu&lt;/code> package provides the full text of every US State of the Union address. Splitting at 1945, the end of the Second World War, reveals how American political vocabulary has shifted over two centuries: from the constitutional and agrarian language of the early republic to the geopolitical and welfare-state vocabulary of the modern era. The loadings table and figure below present the results.&lt;/p>
&lt;pre class="r">&lt;code>if (!requireNamespace(&amp;quot;sotu&amp;quot;, quietly = TRUE)) install.packages(&amp;quot;sotu&amp;quot;)
sotu_texts &amp;lt;- sotu::sotu_text
sotu_years &amp;lt;- sotu::sotu_meta$year
sotu_labels &amp;lt;- ifelse(sotu_years &amp;lt; 1945, &amp;quot;Pre-1945&amp;quot;, &amp;quot;Post-1945&amp;quot;)
res2 &amp;lt;- lsa_pipeline(as.list(sotu_texts), sotu_labels,
grp_a = &amp;quot;Pre-1945&amp;quot;, grp_b = &amp;quot;Post-1945&amp;quot;,
lab_a = &amp;quot;Pre-1945&amp;quot;, lab_b = &amp;quot;Post-1945&amp;quot;,
colour_a = &amp;quot;#E69F00&amp;quot;, colour_b = &amp;quot;#009E73&amp;quot;,
min_docs = 5)&lt;/code>&lt;/pre>
&lt;table>
&lt;caption>&lt;span id="tab:loadings-sotu">Table 2: &lt;/span>&lt;em>Mean PCA Loadings on the First Two Components (Highest Positive Loading per Group in Bold, Excluding Shared)&lt;/em>&lt;/caption>
&lt;thead>
&lt;tr class="header">
&lt;th align="left">Group&lt;/th>
&lt;th align="right">PC1&lt;/th>
&lt;th align="right">PC2&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="left">Pre-1945&lt;/td>
&lt;td align="right">-.845&lt;/td>
&lt;td align="right">-.499&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Post-1945&lt;/td>
&lt;td align="right">-.492&lt;/td>
&lt;td align="right">&lt;strong>.385&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Shared&lt;/td>
&lt;td align="right">-.379&lt;/td>
&lt;td align="right">.132&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="figure" style="text-align: center">&lt;span style="display:block;" id="fig:plot-sotu">&lt;/span>
&lt;div class="plotly html-widget html-fill-item" id="htmlwidget-2" style="width:768px;height:576px;">&lt;/div>
&lt;script type="application/json" data-for="htmlwidget-2">{"x":{"data":[{"x":[0.013287752989669022,0.0015151078484123299,-0.0041639927809794999,0.0024329863389495254,-0.0064838415639756064,-0.00029656493302945364,-0.0050786664995796796,-0.0067667033813527122,-0.004428015965645557,-0.0038366409369963799,-0.0039974776035780419,-0.0058161097063427021,-0.0026112723380078925,-0.0024394203616021188,-0.0046482674401974854],"y":[0.041695332466203217,0.024383169693297253,0.025875377447865128,0.019007361389868749,0.0073319475628275572,0.032911663123940386,0.013545482031131987,0.0041182589008741683,0.010159611319146701,0.0057197970782016262,0.0085645354755251781,0.0029768676043938286,0.016927014200524924,0.0045156386563725724,0.0015016816366281121],"text":["tonight (Post-1945)","jobs (Post-1945)","weve (Post-1945)","americans (Post-1945)","programs (Post-1945)","thats (Post-1945)","help (Post-1945)","program (Post-1945)","budget (Post-1945)","billion (Post-1945)","percent (Post-1945)","soviet (Post-1945)","lets (Post-1945)","nuclear (Post-1945)","economic (Post-1945)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,158,115,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,158,115,1)"}},"hoveron":"points","name":"Post-1945","legendgroup":"Post-1945","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.0059299883753514354,-0.0060110853326906088,-0.0059168280717346849,-0.0059782667234740223,-0.0056107677277599062,-0.0058874592129681599,-0.0055614503444968372,-0.0058008983306079035,-0.0054766275528193324,-0.0055163152625125672,-0.0057213661109132528,-0.0058775943513935504,-0.0054604074907543161,-0.0056906537251830026,-0.0053566471442892177],"y":[-0.016154997431639274,-0.01808959551024486,-0.01698903460044646,-0.016988323911570406,-0.015778337357642263,-0.016229671682749129,-0.015776979601598757,-0.016145812067941891,-0.019396001512634261,-0.014690600254520521,-0.015794162858600122,-0.016220683825330474,-0.01650308897215079,-0.015510408718959881,-0.015930201436391997],"text":["upon (Pre-1945)","spain (Pre-1945)","vessels (Pre-1945)","british (Pre-1945)","mexico (Pre-1945)","subject (Pre-1945)","treasury (Pre-1945)","commerce (Pre-1945)","gentlemen (Pre-1945)","cent (Pre-1945)","duties (Pre-1945)","militia (Pre-1945)","treaty (Pre-1945)","consideration (Pre-1945)","territory (Pre-1945)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(230,159,0,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(230,159,0,1)"}},"hoveron":"points","name":"Pre-1945","legendgroup":"Pre-1945","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.0017478123280863518,0.00068511788801251926,0.022229517128775089,-0.0039339280350563048,-0.004657205911149263,-0.0032278109318195618,-0.0034786200235382152,-0.0014146489141031284,0.11738841084164225,-0.0027155376234720098],"y":[0.0067845141778160936,0.0070376565360968212,0.0066652305444180431,0.0024190192649280085,0.0050877343084827949,0.0010699557114107658,0.00085342072833027415,0.0080398796414144023,-0.014350851383924532,0.0033576016266469869],"text":["america (Shared)","americas (Shared)","thank (Shared)","tax (Shared)","spending (Shared)","million (Shared)","today (Shared)","get (Shared)","applause (Shared)","workers (Shared)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(123,45,142,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(123,45,142,1)"}},"hoveron":"points","name":"Shared","legendgroup":"Shared","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.0059299883753514354,-0.0060110853326906088,-0.0059168280717346849,-0.0059782667234740223,-0.0056107677277599062,-0.0058874592129681599,-0.0055614503444968372,-0.0058008983306079035,-0.0054766275528193324,-0.0055163152625125672,-0.0057213661109132528,-0.0058775943513935504,-0.0054604074907543161,-0.0056906537251830026,-0.0053566471442892177],"y":[-0.016154997431639274,-0.01808959551024486,-0.01698903460044646,-0.016988323911570406,-0.015778337357642263,-0.016229671682749129,-0.015776979601598757,-0.016145812067941891,-0.019396001512634261,-0.014690600254520521,-0.015794162858600122,-0.016220683825330474,-0.01650308897215079,-0.015510408718959881,-0.015930201436391997],"type":"scatter","mode":"text","text":["upon","spain","vessels","british","mexico","subject","treasury","commerce","gentlemen","cent","duties","militia","treaty","consideration","territory"],"textfont":{"size":11,"color":"#E69F00"},"name":"Pre-1945","legendgroup":"Pre-1945","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["upon (Pre-1945)","spain (Pre-1945)","vessels (Pre-1945)","british (Pre-1945)","mexico (Pre-1945)","subject (Pre-1945)","treasury (Pre-1945)","commerce (Pre-1945)","gentlemen (Pre-1945)","cent (Pre-1945)","duties (Pre-1945)","militia (Pre-1945)","treaty (Pre-1945)","consideration (Pre-1945)","territory (Pre-1945)"],"marker":{"color":"rgba(31,119,180,1)","line":{"color":"rgba(31,119,180,1)"}},"error_y":{"color":"rgba(31,119,180,1)"},"error_x":{"color":"rgba(31,119,180,1)"},"line":{"color":"rgba(31,119,180,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.030032055499856242],"y":[0.18983465703366431],"type":"scatter","mode":"markers","marker":{"color":"#E69F00","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(255,127,14,1)"}},"name":"Pre-1945","legendgroup":"Pre-1945","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(255,127,14,1)"},"error_x":{"color":"rgba(255,127,14,1)"},"line":{"color":"rgba(255,127,14,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.0015151078484123299,-0.0041639927809794999,0.0024329863389495254,-0.0064838415639756064,-0.00029656493302945364,-0.0050786664995796796,-0.0067667033813527122,-0.004428015965645557,-0.0038366409369963799,-0.0039974776035780419,-0.0058161097063427021,-0.0026112723380078925,-0.0024394203616021188,-0.0046482674401974854],"y":[0.024383169693297253,0.025875377447865128,0.019007361389868749,0.0073319475628275572,0.032911663123940386,0.013545482031131987,0.0041182589008741683,0.010159611319146701,0.0057197970782016262,0.0085645354755251781,0.0029768676043938286,0.016927014200524924,0.0045156386563725724,0.0015016816366281121],"type":"scatter","mode":"text","text":["jobs","weve","americans","programs","thats","help","program","budget","billion","percent","soviet","lets","nuclear","economic"],"textfont":{"size":11,"color":"#009E73"},"name":"Post-1945","legendgroup":"Post-1945","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["jobs (Post-1945)","weve (Post-1945)","americans (Post-1945)","programs (Post-1945)","thats (Post-1945)","help (Post-1945)","program (Post-1945)","budget (Post-1945)","billion (Post-1945)","percent (Post-1945)","soviet (Post-1945)","lets (Post-1945)","nuclear (Post-1945)","economic (Post-1945)"],"marker":{"color":"rgba(44,160,44,1)","line":{"color":"rgba(44,160,44,1)"}},"error_y":{"color":"rgba(44,160,44,1)"},"error_x":{"color":"rgba(44,160,44,1)"},"line":{"color":"rgba(44,160,44,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.030032055499856242],"y":[0.18983465703366431],"type":"scatter","mode":"markers","marker":{"color":"#009E73","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(214,39,40,1)"}},"name":"Post-1945","legendgroup":"Post-1945","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(214,39,40,1)"},"error_x":{"color":"rgba(214,39,40,1)"},"line":{"color":"rgba(214,39,40,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[-0.0017478123280863518,0.00068511788801251926,-0.0039339280350563048,-0.004657205911149263,-0.0032278109318195618,-0.0034786200235382152,-0.0014146489141031284,-0.0027155376234720098],"y":[0.0067845141778160936,0.0070376565360968212,0.0024190192649280085,0.0050877343084827949,0.0010699557114107658,0.00085342072833027415,0.0080398796414144023,0.0033576016266469869],"type":"scatter","mode":"text","text":["america","americas","tax","spending","million","today","get","workers"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text"],"hovertext":["america (Shared)","americas (Shared)","tax (Shared)","spending (Shared)","million (Shared)","today (Shared)","get (Shared)","workers (Shared)"],"marker":{"color":"rgba(148,103,189,1)","line":{"color":"rgba(148,103,189,1)"}},"error_y":{"color":"rgba(148,103,189,1)"},"error_x":{"color":"rgba(148,103,189,1)"},"line":{"color":"rgba(148,103,189,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.030032055499856242],"y":[0.18983465703366431],"type":"scatter","mode":"markers","marker":{"color":"#7B2D8E","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(140,86,75,1)"}},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(140,86,75,1)"},"error_x":{"color":"rgba(140,86,75,1)"},"line":{"color":"rgba(140,86,75,1)"},"xaxis":"x","yaxis":"y","frame":null}],"layout":{"margin":{"t":16,"r":0,"b":55,"l":51.8057285180573},"paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-0.0073186847645708465,0.0029849677221676597],"tickmode":"array","ticktext":["0.00","0.04","0.08","0.12"],"tickvals":[0,0.040000000000000008,0.080000000000000002,0.12000000000000001],"categoryorder":"array","categoryarray":["0.00","0.04","0.08","0.12"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"y","title":{"text":"Principal Component 1","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-0.02253446139082874,0.036050123002134865],"tickmode":"array","ticktext":["-0.02","0.00","0.02","0.04"],"tickvals":[-0.02,0,0.019999999999999997,0.039999999999999987],"categoryorder":"array","categoryarray":["-0.02","0.00","0.02","0.04"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"x","title":{"text":"Principal Component 2","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","layer":"below","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"#FAFAFA","bordercolor":"#CCCCCC","borderwidth":1,"font":{"color":"rgba(0,0,0,1)","family":"","size":11},"title":{"text":"","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243}},"orientation":"h","x":0.5,"xanchor":"center","y":-0.12,"yanchor":"top","tracegroupgap":2,"itemwidth":30,"itemsizing":"constant","xpad":4,"ypad":4},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"220c4bcf4ffd":{"x":{},"y":{},"colour":{},"text":{},"type":"scatter"},"220c4bcf4ffd.1":{"x":[-0.0059299883753514354,-0.0060110853326906088,-0.0059168280717346849,-0.0059782667234740223,-0.0056107677277599062,-0.0058874592129681599,-0.0055614503444968372,-0.0058008983306079035,-0.0054766275528193324,-0.0055163152625125672,-0.0057213661109132528,-0.0058775943513935504,-0.0054604074907543161,-0.0056906537251830026,-0.0053566471442892177],"y":[-0.016154997431639274,-0.01808959551024486,-0.01698903460044646,-0.016988323911570406,-0.015778337357642263,-0.016229671682749129,-0.015776979601598757,-0.016145812067941891,-0.019396001512634261,-0.014690600254520521,-0.015794162858600122,-0.016220683825330474,-0.01650308897215079,-0.015510408718959881,-0.015930201436391997],"type":"scatter","mode":"text","text":["upon","spain","vessels","british","mexico","subject","treasury","commerce","gentlemen","cent","duties","militia","treaty","consideration","territory"],"textfont":{"size":11,"color":"#E69F00"},"name":"Pre-1945","legendgroup":"Pre-1945","showlegend":false,"hoverinfo":"text","hovertext":["upon (Pre-1945)","spain (Pre-1945)","vessels (Pre-1945)","british (Pre-1945)","mexico (Pre-1945)","subject (Pre-1945)","treasury (Pre-1945)","commerce (Pre-1945)","gentlemen (Pre-1945)","cent (Pre-1945)","duties (Pre-1945)","militia (Pre-1945)","treaty (Pre-1945)","consideration (Pre-1945)","territory (Pre-1945)"],"inherit":false},"220c4bcf4ffd.2":{"x":0.030032055499856242,"y":0.18983465703366431,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#E69F00","opacity":1,"symbol":"circle"},"name":"Pre-1945","legendgroup":"Pre-1945","showlegend":true,"hoverinfo":"skip","inherit":false},"220c4bcf4ffd.3":{"x":[0.0015151078484123299,-0.0041639927809794999,0.0024329863389495254,-0.0064838415639756064,-0.00029656493302945364,-0.0050786664995796796,-0.0067667033813527122,-0.004428015965645557,-0.0038366409369963799,-0.0039974776035780419,-0.0058161097063427021,-0.0026112723380078925,-0.0024394203616021188,-0.0046482674401974854],"y":[0.024383169693297253,0.025875377447865128,0.019007361389868749,0.0073319475628275572,0.032911663123940386,0.013545482031131987,0.0041182589008741683,0.010159611319146701,0.0057197970782016262,0.0085645354755251781,0.0029768676043938286,0.016927014200524924,0.0045156386563725724,0.0015016816366281121],"type":"scatter","mode":"text","text":["jobs","weve","americans","programs","thats","help","program","budget","billion","percent","soviet","lets","nuclear","economic"],"textfont":{"size":11,"color":"#009E73"},"name":"Post-1945","legendgroup":"Post-1945","showlegend":false,"hoverinfo":"text","hovertext":["jobs (Post-1945)","weve (Post-1945)","americans (Post-1945)","programs (Post-1945)","thats (Post-1945)","help (Post-1945)","program (Post-1945)","budget (Post-1945)","billion (Post-1945)","percent (Post-1945)","soviet (Post-1945)","lets (Post-1945)","nuclear (Post-1945)","economic (Post-1945)"],"inherit":false},"220c4bcf4ffd.4":{"x":0.030032055499856242,"y":0.18983465703366431,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#009E73","opacity":1,"symbol":"circle"},"name":"Post-1945","legendgroup":"Post-1945","showlegend":true,"hoverinfo":"skip","inherit":false},"220c4bcf4ffd.5":{"x":[-0.0017478123280863518,0.00068511788801251926,-0.0039339280350563048,-0.004657205911149263,-0.0032278109318195618,-0.0034786200235382152,-0.0014146489141031284,-0.0027155376234720098],"y":[0.0067845141778160936,0.0070376565360968212,0.0024190192649280085,0.0050877343084827949,0.0010699557114107658,0.00085342072833027415,0.0080398796414144023,0.0033576016266469869],"type":"scatter","mode":"text","text":["america","americas","tax","spending","million","today","get","workers"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":"text","hovertext":["america (Shared)","americas (Shared)","tax (Shared)","spending (Shared)","million (Shared)","today (Shared)","get (Shared)","workers (Shared)"],"inherit":false},"220c4bcf4ffd.6":{"x":0.030032055499856242,"y":0.18983465703366431,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#7B2D8E","opacity":1,"symbol":"circle"},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","inherit":false}},"cur_data":"220c4bcf4ffd","visdat":{"220c4bcf4ffd":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":[]}&lt;/script>
&lt;p class="caption">
Figure 2: &lt;em>Word Vectors from US State of the Union Addresses Projected to Two Dimensions, Split at 1945.&lt;/em> Pre-war speeches (amber) feature constitutional and agrarian vocabulary; post-war speeches (green) shift to geopolitical and welfare-state terms. Select an area of the plot to zoom in; double-click to reset.
&lt;/p>
&lt;/div>
&lt;p>The separation is striking. Table 2 reveals that both groups have negative mean loadings on PC1, so the first component does not cleanly separate them; it mainly captures variance shared across eras (general political vocabulary that appears throughout the full 200-year span). The real separation lives on PC2: pre-war words load negatively while post-war words load positively, confirming that the vertical axis in Figure 2 is the one that distinguishes the two eras. Pre-war presidents address ‘gentlemen’ (the formal salutation of a different era) and discuss ‘vessels’, ‘militia’, ‘commerce’ and ‘treasury’ – the vocabulary of a young republic preoccupied with trade, territorial expansion and the mechanics of governance. Modern presidents speak of ‘tonight’ (State of the Union addresses have been televised since the 1960s), ‘jobs’, ‘nuclear’ and ‘program’ – the vocabulary of a superpower managing a welfare state and a global military presence. Words like ‘congress’, ‘government’, ‘war’ and ‘people’ anchor both eras, sitting in the shared middle ground.&lt;/p>
&lt;/div>
&lt;div id="imdb-film-reviews-positive-vs-negative" class="section level3">
&lt;h3>IMDB Film Reviews: Positive vs Negative&lt;/h3>
&lt;p>Now a harder test. The &lt;code>text2vec&lt;/code> package includes 5,000 IMDB film reviews labelled as positive or negative – a classic sentiment-analysis benchmark. Unlike the two corpora above, the split here is not by topic but by evaluative tone. Both positive and negative reviews discuss films, characters, plots and acting; the difference lies in the adjectives and evaluative phrasing. This makes the separation task far harder for a simple co-occurrence model – and the result is instructive. The loadings table and figure below present the results.&lt;/p>
&lt;pre class="r">&lt;code>if (!requireNamespace(&amp;quot;text2vec&amp;quot;, quietly = TRUE)) install.packages(&amp;quot;text2vec&amp;quot;)
data(&amp;quot;movie_review&amp;quot;, package = &amp;quot;text2vec&amp;quot;)
mv_labels &amp;lt;- ifelse(movie_review$sentiment == 1, &amp;quot;Positive&amp;quot;, &amp;quot;Negative&amp;quot;)
res3 &amp;lt;- lsa_pipeline(as.list(movie_review$review), mv_labels,
grp_a = &amp;quot;Positive&amp;quot;, grp_b = &amp;quot;Negative&amp;quot;,
lab_a = &amp;quot;Positive&amp;quot;, lab_b = &amp;quot;Negative&amp;quot;,
colour_a = &amp;quot;#009E73&amp;quot;, colour_b = &amp;quot;#D55E00&amp;quot;,
min_docs = 50)&lt;/code>&lt;/pre>
&lt;table>
&lt;caption>&lt;span id="tab:loadings-imdb">Table 3: &lt;/span>&lt;em>Mean PCA Loadings on the First Two Components (Highest Positive Loading per Group in Bold, Excluding Shared)&lt;/em>&lt;/caption>
&lt;thead>
&lt;tr class="header">
&lt;th align="left">Group&lt;/th>
&lt;th align="right">PC1&lt;/th>
&lt;th align="right">PC2&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="left">Negative&lt;/td>
&lt;td align="right">&lt;strong>.329&lt;/strong>&lt;/td>
&lt;td align="right">-.255&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Positive&lt;/td>
&lt;td align="right">-.081&lt;/td>
&lt;td align="right">&lt;strong>.192&lt;/strong>&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Shared&lt;/td>
&lt;td align="right">.103&lt;/td>
&lt;td align="right">.281&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div class="figure" style="text-align: center">&lt;span style="display:block;" id="fig:plot-imdb">&lt;/span>
&lt;div class="plotly html-widget html-fill-item" id="htmlwidget-3" style="width:768px;height:576px;">&lt;/div>
&lt;script type="application/json" data-for="htmlwidget-3">{"x":{"data":[{"x":[0.18571654615554042,0.099809048091466776,0.54682437946265205,0.36439482278066504,0.1271384093140395,0.010783944221508043,-0.0063987379304191756,0.17527218291872354,0.11769089497754716,0.011732048948378102,0.40392818628601812,0.028398043898213224,0.15777405945755296,0.10697917310366636,0.074886297073802885],"y":[-0.23334987004789814,-0.17579882921465306,-1.1752727275347559,-0.98471194409893514,-0.17245095481958869,-0.10061200644101291,-0.13837537217875012,-0.15878048299828953,-0.14217651842001292,-0.010123057993395339,-0.74957240804973946,-0.16231526431483859,-0.26943787686463971,-0.027475471610646077,-0.18593059282974145],"text":["bad (Negative)","worst (Negative)","waste (Negative)","awful (Negative)","poor (Negative)","nothing (Negative)","stupid (Negative)","terrible (Negative)","worse (Negative)","even (Negative)","script (Negative)","boring (Negative)","money (Negative)","plot (Negative)","horrible (Negative)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(213,94,0,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(213,94,0,1)"}},"hoveron":"points","name":"Negative","legendgroup":"Negative","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.081744018423949641,-0.047571536237173584,-0.10790862327796238,-0.0090255765592872038,-0.080712604885222236,-0.12532619741627082,-0.029145246140461999,0.073327862399543531,0.067948240498652099,-0.057808595192257631,0.010966278713061849,-0.083590897681595416,0.010950317928239492,-0.0048006452696497818,-0.028322253846350821],"y":[0.46046284257107145,0.25777241131156203,0.22260967753319263,0.17887405184315525,0.28082563733867594,0.26691602855778812,0.18979696029567342,0.12467808537344016,0.086506620780249399,0.11553624444403925,0.067215601055555421,0.21969682869980814,0.10874128923843671,0.09570158770482054,0.15495837890857736],"text":["great (Positive)","excellent (Positive)","best (Positive)","wonderful (Positive)","love (Positive)","family (Positive)","loved (Positive)","beautiful (Positive)","highly (Positive)","fun (Positive)","perfect (Positive)","also (Positive)","young (Positive)","favorite (Positive)","life (Positive)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(0,158,115,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(0,158,115,1)"}},"hoveron":"points","name":"Positive","legendgroup":"Positive","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[0.2432130402373899,0.16955934027247727,-0.01056565525436497,-0.015944273052570485,-0.034182546658513897,-0.06192679310864109,0.066431080163338083,-0.018622098253129622,0.037747591349934988,-2.2878754890645903],"y":[0.50445274476249602,0.39116896728561923,0.29371423476444708,0.182290602545849,0.16064197365573799,0.11595431615189583,0.37509156551691564,0.2460104522233707,0.21928355658824175,-0.6325172817337219],"text":["movie (Shared)","film (Shared)","good (Shared)","one (Shared)","like (Shared)","just (Shared)","story (Shared)","really (Shared)","see (Shared)","show (Shared)"],"type":"scatter","mode":"markers","marker":{"autocolorscale":false,"color":"rgba(123,45,142,1)","opacity":0,"size":0.10000000000000001,"symbol":"circle","line":{"width":1.8897637795275593,"color":"rgba(123,45,142,1)"}},"hoveron":"points","name":"Shared","legendgroup":"Shared","showlegend":false,"xaxis":"x","yaxis":"y","hoverinfo":"text","frame":null},{"x":[-0.081744018423949641,-0.047571536237173584,-0.10790862327796238,-0.0090255765592872038,-0.080712604885222236,-0.12532619741627082,-0.029145246140461999,0.073327862399543531,0.067948240498652099,-0.057808595192257631,0.010966278713061849,-0.083590897681595416,0.010950317928239492,-0.0048006452696497818,-0.028322253846350821],"y":[0.46046284257107145,0.25777241131156203,0.22260967753319263,0.17887405184315525,0.28082563733867594,0.26691602855778812,0.18979696029567342,0.12467808537344016,0.086506620780249399,0.11553624444403925,0.067215601055555421,0.21969682869980814,0.10874128923843671,0.09570158770482054,0.15495837890857736],"type":"scatter","mode":"text","text":["great","excellent","best","wonderful","love","family","loved","beautiful","highly","fun","perfect","also","young","favorite","life"],"textfont":{"size":11,"color":"#009E73"},"name":"Positive","legendgroup":"Positive","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["great (Positive)","excellent (Positive)","best (Positive)","wonderful (Positive)","love (Positive)","family (Positive)","loved (Positive)","beautiful (Positive)","highly (Positive)","fun (Positive)","perfect (Positive)","also (Positive)","young (Positive)","favorite (Positive)","life (Positive)"],"marker":{"color":"rgba(31,119,180,1)","line":{"color":"rgba(31,119,180,1)"}},"error_y":{"color":"rgba(31,119,180,1)"},"error_x":{"color":"rgba(31,119,180,1)"},"line":{"color":"rgba(31,119,180,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.9916913373928846],"y":[4.9719468113467888],"type":"scatter","mode":"markers","marker":{"color":"#009E73","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(255,127,14,1)"}},"name":"Positive","legendgroup":"Positive","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(255,127,14,1)"},"error_x":{"color":"rgba(255,127,14,1)"},"line":{"color":"rgba(255,127,14,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.18571654615554042,0.099809048091466776,0.36439482278066504,0.1271384093140395,0.010783944221508043,-0.0063987379304191756,0.17527218291872354,0.11769089497754716,0.011732048948378102,0.40392818628601812,0.028398043898213224,0.15777405945755296,0.10697917310366636,0.074886297073802885],"y":[-0.23334987004789814,-0.17579882921465306,-0.98471194409893514,-0.17245095481958869,-0.10061200644101291,-0.13837537217875012,-0.15878048299828953,-0.14217651842001292,-0.010123057993395339,-0.74957240804973946,-0.16231526431483859,-0.26943787686463971,-0.027475471610646077,-0.18593059282974145],"type":"scatter","mode":"text","text":["bad","worst","awful","poor","nothing","stupid","terrible","worse","even","script","boring","money","plot","horrible"],"textfont":{"size":11,"color":"#D55E00"},"name":"Negative","legendgroup":"Negative","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text","text","text","text","text","text"],"hovertext":["bad (Negative)","worst (Negative)","awful (Negative)","poor (Negative)","nothing (Negative)","stupid (Negative)","terrible (Negative)","worse (Negative)","even (Negative)","script (Negative)","boring (Negative)","money (Negative)","plot (Negative)","horrible (Negative)"],"marker":{"color":"rgba(44,160,44,1)","line":{"color":"rgba(44,160,44,1)"}},"error_y":{"color":"rgba(44,160,44,1)"},"error_x":{"color":"rgba(44,160,44,1)"},"line":{"color":"rgba(44,160,44,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.9916913373928846],"y":[4.9719468113467888],"type":"scatter","mode":"markers","marker":{"color":"#D55E00","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(214,39,40,1)"}},"name":"Negative","legendgroup":"Negative","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(214,39,40,1)"},"error_x":{"color":"rgba(214,39,40,1)"},"line":{"color":"rgba(214,39,40,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[0.2432130402373899,0.16955934027247727,-0.01056565525436497,-0.015944273052570485,-0.034182546658513897,-0.06192679310864109,0.066431080163338083,-0.018622098253129622,0.037747591349934988],"y":[0.50445274476249602,0.39116896728561923,0.29371423476444708,0.182290602545849,0.16064197365573799,0.11595431615189583,0.37509156551691564,0.2460104522233707,0.21928355658824175],"type":"scatter","mode":"text","text":["movie","film","good","one","like","just","story","really","see"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":["text","text","text","text","text","text","text","text","text"],"hovertext":["movie (Shared)","film (Shared)","good (Shared)","one (Shared)","like (Shared)","just (Shared)","story (Shared)","really (Shared)","see (Shared)"],"marker":{"color":"rgba(148,103,189,1)","line":{"color":"rgba(148,103,189,1)"}},"error_y":{"color":"rgba(148,103,189,1)"},"error_x":{"color":"rgba(148,103,189,1)"},"line":{"color":"rgba(148,103,189,1)"},"xaxis":"x","yaxis":"y","frame":null},{"x":[1.9916913373928846],"y":[4.9719468113467888],"type":"scatter","mode":"markers","marker":{"color":"#7B2D8E","size":12,"opacity":1,"symbol":"circle","line":{"color":"rgba(140,86,75,1)"}},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","error_y":{"color":"rgba(140,86,75,1)"},"error_x":{"color":"rgba(140,86,75,1)"},"line":{"color":"rgba(140,86,75,1)"},"xaxis":"x","yaxis":"y","frame":null}],"layout":{"margin":{"t":16,"r":0,"b":55,"l":45.429638854296407},"paper_bgcolor":"rgba(255,255,255,1)","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"xaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-0.15708146043840815,0.43568344930815545],"tickmode":"array","ticktext":["-2","-1","0"],"tickvals":[-2,-1,0],"categoryorder":"array","categoryarray":["-2","-1","0"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"y","title":{"text":"Principal Component 1","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"yaxis":{"domain":[0,1],"automargin":true,"type":"linear","autorange":false,"range":[-1.0740618254306211,0.59380262609418188],"tickmode":"array","ticktext":["-1.0","-0.5","0.0","0.5"],"tickvals":[-1,-0.5,0,0.5],"categoryorder":"array","categoryarray":["-1.0","-0.5","0.0","0.5"],"nticks":null,"ticks":"","tickcolor":null,"ticklen":3.9850560398505608,"tickwidth":0,"showticklabels":true,"tickfont":{"color":"rgba(77,77,77,1)","family":"","size":12.7521793275218},"tickangle":-0,"showline":false,"linecolor":null,"linewidth":0,"showgrid":true,"gridcolor":"rgba(235,235,235,1)","gridwidth":0,"zeroline":false,"anchor":"x","title":{"text":"Principal Component 2","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243},"standoff":8},"hoverformat":".2f"},"shapes":[{"type":"rect","fillcolor":null,"line":{"color":null,"width":0,"linetype":[]},"yref":"paper","xref":"paper","layer":"below","x0":0,"x1":1,"y0":0,"y1":1}],"showlegend":true,"legend":{"bgcolor":"#FAFAFA","bordercolor":"#CCCCCC","borderwidth":1,"font":{"color":"rgba(0,0,0,1)","family":"","size":11},"title":{"text":"","font":{"color":"rgba(0,0,0,1)","family":"","size":15.940224159402243}},"orientation":"h","x":0.5,"xanchor":"center","y":-0.12,"yanchor":"top","tracegroupgap":2,"itemwidth":30,"itemsizing":"constant","xpad":4,"ypad":4},"hovermode":"closest","barmode":"relative"},"config":{"doubleClick":"reset","modeBarButtonsToAdd":["hoverclosest","hovercompare"],"showSendToCloud":false},"source":"A","attrs":{"220c5dd16a36":{"x":{},"y":{},"colour":{},"text":{},"type":"scatter"},"220c5dd16a36.1":{"x":[-0.081744018423949641,-0.047571536237173584,-0.10790862327796238,-0.0090255765592872038,-0.080712604885222236,-0.12532619741627082,-0.029145246140461999,0.073327862399543531,0.067948240498652099,-0.057808595192257631,0.010966278713061849,-0.083590897681595416,0.010950317928239492,-0.0048006452696497818,-0.028322253846350821],"y":[0.46046284257107145,0.25777241131156203,0.22260967753319263,0.17887405184315525,0.28082563733867594,0.26691602855778812,0.18979696029567342,0.12467808537344016,0.086506620780249399,0.11553624444403925,0.067215601055555421,0.21969682869980814,0.10874128923843671,0.09570158770482054,0.15495837890857736],"type":"scatter","mode":"text","text":["great","excellent","best","wonderful","love","family","loved","beautiful","highly","fun","perfect","also","young","favorite","life"],"textfont":{"size":11,"color":"#009E73"},"name":"Positive","legendgroup":"Positive","showlegend":false,"hoverinfo":"text","hovertext":["great (Positive)","excellent (Positive)","best (Positive)","wonderful (Positive)","love (Positive)","family (Positive)","loved (Positive)","beautiful (Positive)","highly (Positive)","fun (Positive)","perfect (Positive)","also (Positive)","young (Positive)","favorite (Positive)","life (Positive)"],"inherit":false},"220c5dd16a36.2":{"x":1.9916913373928846,"y":4.9719468113467888,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#009E73","opacity":1,"symbol":"circle"},"name":"Positive","legendgroup":"Positive","showlegend":true,"hoverinfo":"skip","inherit":false},"220c5dd16a36.3":{"x":[0.18571654615554042,0.099809048091466776,0.36439482278066504,0.1271384093140395,0.010783944221508043,-0.0063987379304191756,0.17527218291872354,0.11769089497754716,0.011732048948378102,0.40392818628601812,0.028398043898213224,0.15777405945755296,0.10697917310366636,0.074886297073802885],"y":[-0.23334987004789814,-0.17579882921465306,-0.98471194409893514,-0.17245095481958869,-0.10061200644101291,-0.13837537217875012,-0.15878048299828953,-0.14217651842001292,-0.010123057993395339,-0.74957240804973946,-0.16231526431483859,-0.26943787686463971,-0.027475471610646077,-0.18593059282974145],"type":"scatter","mode":"text","text":["bad","worst","awful","poor","nothing","stupid","terrible","worse","even","script","boring","money","plot","horrible"],"textfont":{"size":11,"color":"#D55E00"},"name":"Negative","legendgroup":"Negative","showlegend":false,"hoverinfo":"text","hovertext":["bad (Negative)","worst (Negative)","awful (Negative)","poor (Negative)","nothing (Negative)","stupid (Negative)","terrible (Negative)","worse (Negative)","even (Negative)","script (Negative)","boring (Negative)","money (Negative)","plot (Negative)","horrible (Negative)"],"inherit":false},"220c5dd16a36.4":{"x":1.9916913373928846,"y":4.9719468113467888,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#D55E00","opacity":1,"symbol":"circle"},"name":"Negative","legendgroup":"Negative","showlegend":true,"hoverinfo":"skip","inherit":false},"220c5dd16a36.5":{"x":[0.2432130402373899,0.16955934027247727,-0.01056565525436497,-0.015944273052570485,-0.034182546658513897,-0.06192679310864109,0.066431080163338083,-0.018622098253129622,0.037747591349934988],"y":[0.50445274476249602,0.39116896728561923,0.29371423476444708,0.182290602545849,0.16064197365573799,0.11595431615189583,0.37509156551691564,0.2460104522233707,0.21928355658824175],"type":"scatter","mode":"text","text":["movie","film","good","one","like","just","story","really","see"],"textfont":{"size":11,"color":"#7B2D8E"},"name":"Shared","legendgroup":"Shared","showlegend":false,"hoverinfo":"text","hovertext":["movie (Shared)","film (Shared)","good (Shared)","one (Shared)","like (Shared)","just (Shared)","story (Shared)","really (Shared)","see (Shared)"],"inherit":false},"220c5dd16a36.6":{"x":1.9916913373928846,"y":4.9719468113467888,"type":"scatter","mode":"markers","marker":{"size":12,"color":"#7B2D8E","opacity":1,"symbol":"circle"},"name":"Shared","legendgroup":"Shared","showlegend":true,"hoverinfo":"skip","inherit":false}},"cur_data":"220c5dd16a36","visdat":{"220c5dd16a36":["function (y) ","x"]},"highlight":{"on":"plotly_click","persistent":false,"dynamic":false,"selectize":false,"opacityDim":0.20000000000000001,"selected":{"opacity":1},"debounce":0},"shinyEvents":["plotly_hover","plotly_click","plotly_selected","plotly_relayout","plotly_brushed","plotly_brushing","plotly_clickannotation","plotly_doubleclick","plotly_deselect","plotly_afterplot","plotly_sunburstclick"],"base_url":"https://plot.ly"},"evals":[],"jsHooks":[]}&lt;/script>
&lt;p class="caption">
Figure 3: &lt;em>Word Vectors from 5,000 IMDB Film Reviews (Positive vs Negative) Projected to Two Dimensions.&lt;/em> Unlike the clean topic-based separations in the Reuters and SOTU corpora, the sentiment-based distinction is much muddier: positive and negative reviews share most of their vocabulary, and evaluative words overlap heavily. Select an area of the plot to zoom in; double-click to reset.
&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="what-the-plots-capture-and-what-they-miss" class="section level3">
&lt;h3>What the Plots Capture – and What They Miss&lt;/h3>
&lt;p>Taken together, Figures 1–3 illustrate both the power and the limits of distributional models. Figure 1 captures the real-world distinction between financial and energy markets with striking clarity: domain-specific vocabulary clusters tightly, and a polysemous word like ‘price’ lands in different positions depending on its dominant context – precisely the kind of structure that Louwerse and colleagues have documented at larger scale. Figure 2 captures genuine historical change: pre-war addresses use the vocabulary of a young republic (‘gentlemen’, ‘militia’, ‘vessels’); modern ones use the vocabulary of a superpower (‘tonight’, ‘jobs’, ‘nuclear’), reflecting two centuries of political evolution.&lt;/p>
&lt;p>Figure 3, however, reveals a clear limitation. Because both positive and negative reviews discuss the same subject – films – the topical vocabulary is largely shared, and the evaluative words that do separate them (‘excellent’ vs ‘worst’, for instance) form only a thin layer atop a large common vocabulary. A 20-dimensional LSA space simply lacks the resolution to untangle sentiment from topic. The model captures &lt;em>what&lt;/em> people write about more easily than &lt;em>how&lt;/em> they feel about it.&lt;/p>
&lt;p>These imprecisions are not accidental; they reflect a fundamental constraint: model capacity.&lt;/p>
&lt;/div>
&lt;div id="from-toy-models-to-titans" class="section level2">
&lt;h2>From Toy Models to Titans&lt;/h2>
&lt;p>The LSA spaces above used just 20 latent dimensions, trained on corpora of a few dozen to a few thousand documents. The surviving vocabulary numbers in the low thousands. Under these conditions, the model does a remarkable job of sorting finance from energy or 19th-century language from modern, but it lacks the capacity to encode the subtler distributional cues that distinguish evaluative tone, sarcasm or register.&lt;/p>
&lt;p>The history of distributional models is, in large part, a history of scale. As &lt;a href="https://doi.org/10.1177/09637214241242746">Connell and Lynott (2024)&lt;/a> illustrate, growth in model size over the past three decades has been staggering. The LSA models of the late 1990s (&lt;a href="https://doi.org/10.1037/0033-295X.104.2.211">Landauer &amp;amp; Dumais, 1997&lt;/a>) had a few hundred latent dimensions and were trained on roughly 30,000 documents, already enough to pass synonym tests at near-human levels. Word2Vec (&lt;a href="https://doi.org/10.48550/arXiv.1301.3781">Mikolov et al., 2013&lt;/a>) moved to shallow neural networks with a few million learnable parameters trained on billions of words. Then came the Transformer-based models, and the scale exploded: BERT (&lt;a href="https://doi.org/10.18653/v1/N19-1423">Devlin et al., 2019&lt;/a>) had 340 million parameters, GPT-3 (&lt;a href="https://doi.org/10.48550/arXiv.2005.14165">Brown et al., 2020&lt;/a>) reached 175 billion, and today’s largest models are estimated at well over a trillion parameters, trained on text corpora so vast they encompass a substantial fraction of everything ever written on the internet.&lt;/p>
&lt;p>The core principle has not changed: predict the next word on the basis of the company it keeps. What changed is scale. A model with 20 dimensions and 10,000 words can distinguish finance from energy; a model with billions of parameters and trillions of training tokens can distinguish a Shakespearean sonnet from a legal brief, track the implications of a subordinate clause across a 3,000-word passage and generate fluent prose in dozens of languages. Generative AI was not built on a fundamentally new idea about language – it was built by scaling Firth’s old idea up by many orders of magnitude and combining it with a crucial algorithmic innovation.&lt;/p>
&lt;/div>
&lt;div id="the-transformer-revolution" class="section level2">
&lt;h2>The Transformer Revolution&lt;/h2>
&lt;p>That algorithmic innovation was the Transformer, introduced by &lt;a href="https://doi.org/10.48550/arXiv.1706.03762">Vaswani et al.&lt;/a> in their 2017 paper ‘Attention Is All You Need’. Earlier language models relied on recurrent or convolutional neural networks, which processed words sequentially – reading a sentence one word at a time while trying to hold everything so far in memory. The approach worked, but imperfectly: it was slow and struggled with long-range dependencies.&lt;/p>
&lt;p>The Transformer replaced all of that with &lt;em>multi-head self-attention&lt;/em>: a mechanism that lets the model weigh every word in a passage simultaneously, comparing each one directly with every other. In plain terms, attention allows the model to ask, for each word, ‘which other words here matter most for understanding me?’ The idea is simple but transformative. It outperformed existing models on translation and a host of other tasks, without any recurrence or convolution, and was far faster to train in parallel.&lt;/p>
&lt;p>With Transformers in hand, NLP entered a new era. Large pretrained models like BERT (&lt;a href="https://doi.org/10.18653/v1/N19-1423">Devlin et al., 2019&lt;/a>) and the GPT series (&lt;a href="https://doi.org/10.48550/arXiv.2005.14165">Brown et al., 2020&lt;/a>) set successive benchmarks for language understanding and generation. The combination of the Transformer architecture with the massive scale described above – hundreds of billions of parameters trained on essentially the whole internet – is what made generative AI possible. From Firth’s insight about co-occurrence, through LSA’s matrix decompositions and Word2Vec’s neural embeddings, to the attention-powered behemoths of today, the thread is continuous. But despite their extraordinary power, these models remain &lt;em>predictors of text&lt;/em>, not infallible oracles of truth. The Transformer revolution made the storyteller more eloquent; it did not make the storyteller more honest.&lt;/p>
&lt;/div>
&lt;div id="fluency-is-not-truth" class="section level2">
&lt;h2>Fluency Is Not Truth&lt;/h2>
&lt;p>Crucially, LLMs are optimised for fluency, not truth. They have no built-in fact-checking; they simply predict plausible continuations. As &lt;a href="https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf">Radford et al. (2019)&lt;/a> showed with GPT-2, the training objective is straightforward: learn to predict the next token in a sequence, given all preceding tokens. The loss function rewards fluent, likely text – but it never rewards the model for replying ‘I don’t know.’ &lt;a href="https://doi.org/10.18653/v1/2022.acl-long.229">Lin et al. (2022)&lt;/a> demonstrated with their TruthfulQA benchmark that models frequently produce confident but false answers rather than admitting uncertainty, and that larger models can actually perform &lt;em>worse&lt;/em> on truthfulness because they are better at reproducing convincing-sounding misinformation from their training data. The upshot: models tend to guess when unsure, and they guess with alarming confidence.&lt;/p>
&lt;p>Consider what this means in practice. Ask an LLM about a niche historical event, and it may cheerfully invent plausible-sounding details – dates, names, citations – that are entirely fabricated. Ask it about a scientific finding at the edges of its training data, and it may blend two real studies into one fictional hybrid, complete with a convincing journal name. This phenomenon, known as &lt;em>hallucination&lt;/em>, is not a bug that will eventually be patched away. &lt;a href="https://doi.org/10.48550/arXiv.2401.11817">Xu et al. (2024)&lt;/a> demonstrated formally that if an LLM cannot reliably distinguish true from false statements in its training data, hallucinations are mathematically inevitable – a structural consequence of the architecture itself. The model’s very fluency becomes its greatest liability: it weaves a convincing narrative whether or not the underlying facts support it. In short, current LLMs are trained to be good &lt;em>storytellers&lt;/em>, not guaranteed &lt;em>truth-tellers&lt;/em>.&lt;/p>
&lt;/div>
&lt;div id="why-prompts-matter-and-why-one-is-rarely-enough" class="section level2">
&lt;h2>Why Prompts Matter – and Why One Is Rarely Enough&lt;/h2>
&lt;p>Because of this predictive nature, prompt engineering is essential. A vague or generic question will often yield a superficial, off‑target or simply wrong answer. One &lt;a href="https://cloud.google.com/discover/what-is-prompt-engineering">guide defines prompt engineering&lt;/a> as ‘the art and science of designing and optimising prompts to guide AI models towards generating the desired responses’. That sounds rather grand, but in practice it often means something as prosaic as adding context, specifying a format, giving an example or two, and then refining iteratively until the output is actually useful.&lt;/p>
&lt;p>The sensitivity of LLMs to phrasing is remarkable – and, on first encounter, humbling. Asking ‘What are some criticisms of capitalism?’ and ‘What are the main drawbacks of market economies?’ can elicit strikingly different responses, even though the questions are conceptually near‑identical. &lt;a href="https://doi.org/10.48550/arXiv.2310.11324">Sclar et al. (2024)&lt;/a> showed that even tiny changes – swapping a single word, reordering a clause, adding an explicit instruction to be concise – can dramatically alter what a model produces, with performance varying by up to 76 percentage points across prompt formats for the same task. &lt;a href="https://doi.org/10.1038/s41746-024-01029-4">Wang et al. (2024)&lt;/a> found that well-engineered prompts can yield ‘ideal and stable answers’, but that different formulations can have very different effects on performance. Researchers testing LLMs rigorously often try dozens of prompt variants to achieve reliable output. A single query is, in most cases, simply not enough.&lt;/p>
&lt;p>There is also the matter of &lt;em>role&lt;/em>, &lt;em>tone&lt;/em> and &lt;em>constraints&lt;/em>. Instructing the model to respond as a sceptical scientist, a sympathetic teacher or a meticulous copy‑editor changes its behaviour markedly. Asking it to respond in plain English, to avoid jargon, to stay under 150 words or to number its assumptions shapes the answer in ways a bare question never could. Each of these additions is, in Firth’s terms, part of the ‘company’ the prompt keeps – and consequently part of what determines the model’s response.&lt;/p>
&lt;/div>
&lt;div id="what-good-prompting-looks-like" class="section level2">
&lt;h2>What Good Prompting Looks Like&lt;/h2>
&lt;p>Treat an LLM as a collaborator requiring careful, iterative guidance – not a search engine that delivers verdicts on demand. Provide ample background in your prompt, and invite the model to clarify anything before responding. Consider the first reply a draft, not a conclusion. Push back on suspect claims, request sources or alternative views, and rephrase when the model goes off track. Press further: ask it to explain its reasoning, consider counter-arguments and flag what it is uncertain about. Each move draws more of the model’s latent capability to the surface.&lt;/p>
&lt;p>This iterative approach mirrors good intellectual practice more generally. A scientist does not run one experiment and publish; they replicate, vary conditions and triangulate across methods. A journalist does not accept a single source; they seek corroboration. A doctor does not diagnose on one symptom; they gather a fuller picture. Using an LLM well requires the same instinct: treat each exchange as one data point in an ongoing investigation, not as the final word.&lt;/p>
&lt;/div>
&lt;div id="a-powerful-tool-not-an-oracle" class="section level2">
&lt;h2>A Powerful Tool, Not an Oracle&lt;/h2>
&lt;p>Using an LLM is a bit like navigating a foreign city without a map: you will stumble upon genuinely useful places, but you will also take wrong turns, end up in dead ends, and occasionally find yourself confidently heading in exactly the wrong direction. These models will often produce accurate information, because language genuinely encodes reality – words cluster around what they describe, and texts about geography, commodity markets or sensory properties track how the world actually works (&lt;a href="https://doi.org/10.1111/j.1551-6709.2008.01003.x">Louwerse &amp;amp; Zwaan, 2009&lt;/a>; &lt;a href="https://doi.org/10.1111/j.1756-8765.2010.01106.x">Louwerse, 2011&lt;/a>). But an LLM is trained to be fluent, not truthful: hallucinations are a mathematical inevitability of the architecture (&lt;a href="https://doi.org/10.48550/arXiv.2401.11817">Xu et al., 2024&lt;/a>). The underlying mechanism is still word co-occurrence – Firth’s old principle, scaled up. Neither the brute force of massive training data (&lt;a href="https://doi.org/10.1177/09637214241242746">Connell &amp;amp; Lynott, 2024&lt;/a>) nor the ingenious attention mechanisms of modern architectures (&lt;a href="https://doi.org/10.48550/arXiv.1706.03762">Vaswani et al., 2017&lt;/a>) has &lt;em>yet&lt;/em> tamed this heuristic machine into a reliable truth-teller.&lt;/p>
&lt;p>Good results take deliberate effort. A well-crafted prompt, with specific context, clear constraints, iterative refinement and healthy scepticism, does not transform the model into a truth engine. What it does is steer its predictions towards the regions of language that most faithfully reflect the world. Skip that effort, and arriving at the right destination becomes a matter of luck rather than design.&lt;/p>
&lt;p>Firth’s insight about words applies equally to prompts: you shall know an answer by the company the question keeps (&lt;a href="https://doi.org/10.48550/arXiv.2411.10541">He et al., 2024&lt;/a>; &lt;a href="https://doi.org/10.1038/s41746-024-01029-4">Wang et al., 2024&lt;/a>).&lt;/p>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em> [Doctoral thesis, Lancaster University]. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Brown, T. B., Mann, B., Ryder, N., Subbiah, M., Kaplan, J., Dhariwal, P., Neelakantan, A., Shyam, P., Sastry, G., Askell, A., Agarwal, S., Herbert-Voss, A., Krueger, G., Henighan, T., Child, R., Ramesh, A., Ziegler, D. M., Wu, J., Winter, C., … Amodei, D. (2020). Language models are few-shot learners. In &lt;em>Advances in Neural Information Processing Systems&lt;/em> (Vol. 33, pp. 1877–1901). &lt;a href="https://doi.org/10.48550/arXiv.2005.14165" class="uri">https://doi.org/10.48550/arXiv.2005.14165&lt;/a>&lt;/p>
&lt;p>Brunila, M., &amp;amp; LaViolette, J. (2022). What company do words keep? Revisiting the distributional semantics of J.R. Firth &amp;amp; Zellig Harris. &lt;em>Proceedings of NAACL 2022&lt;/em>. &lt;a href="https://doi.org/10.18653/v1/2022.naacl-main.327" class="uri">https://doi.org/10.18653/v1/2022.naacl-main.327&lt;/a>&lt;/p>
&lt;p>Connell, L., &amp;amp; Lynott, D. (2024). What can language models tell us about human cognition? &lt;em>Current Directions in Psychological Science&lt;/em>. &lt;a href="https://doi.org/10.1177/09637214241242746" class="uri">https://doi.org/10.1177/09637214241242746&lt;/a>&lt;/p>
&lt;p>Devlin, J., Chang, M.-W., Lee, K., &amp;amp; Toutanova, K. (2019). BERT: Pre-training of deep bidirectional transformers for language understanding. In &lt;em>Proceedings of NAACL-HLT 2019&lt;/em> (pp. 4171–4186). Association for Computational Linguistics. &lt;a href="https://doi.org/10.18653/v1/N19-1423" class="uri">https://doi.org/10.18653/v1/N19-1423&lt;/a>&lt;/p>
&lt;p>Feinerer, I., Hornik, K., &amp;amp; Meyer, D. (2008). Text mining infrastructure in R. &lt;em>Journal of Statistical Software, 25&lt;/em>(5), 1–54. &lt;a href="https://doi.org/10.18637/jss.v025.i05" class="uri">https://doi.org/10.18637/jss.v025.i05&lt;/a>&lt;/p>
&lt;p>Firth, J. R. (1957). &lt;em>Studies in Linguistic Analysis&lt;/em>. Basil Blackwell.&lt;/p>
&lt;p>Günther, F., Dudschig, C., &amp;amp; Kaup, B. (2016). LSAfun: An R package for computations based on Latent Semantic Analysis. &lt;em>Behavior Research Methods, 48&lt;/em>(2), 409-421. &lt;a href="https://doi.org/10.3758/s13428-015-0662-x" class="uri">https://doi.org/10.3758/s13428-015-0662-x&lt;/a>&lt;/p>
&lt;p>He, J., Rungta, M., Koleczek, D., Sekhon, A., Wang, F. X., &amp;amp; Hasan, S. (2024). Does prompt formatting have any impact on LLM performance? &lt;em>arXiv&lt;/em>. &lt;a href="https://doi.org/10.48550/arXiv.2411.10541" class="uri">https://doi.org/10.48550/arXiv.2411.10541&lt;/a>&lt;/p>
&lt;p>Landauer, T. K., &amp;amp; Dumais, S. T. (1997). A solution to Plato’s problem: The latent semantic analysis theory of acquisition, induction, and representation of knowledge. &lt;em>Psychological Review, 104&lt;/em>(2), 211–240. &lt;a href="https://doi.org/10.1037/0033-295X.104.2.211" class="uri">https://doi.org/10.1037/0033-295X.104.2.211&lt;/a>&lt;/p>
&lt;p>Lewis, D. D. (1997). &lt;em>Reuters-21578 text categorization test collection, distribution 1.0&lt;/em> [Dataset]. AT&amp;amp;T Bell Laboratories. &lt;a href="http://kdd.ics.uci.edu/databases/reuters21578/reuters21578.html" class="uri">http://kdd.ics.uci.edu/databases/reuters21578/reuters21578.html&lt;/a>&lt;/p>
&lt;p>Lin, S., Hilton, J., &amp;amp; Evans, O. (2022). TruthfulQA: Measuring how models mimic human falsehoods. In &lt;em>Proceedings of the 60th Annual Meeting of the Association for Computational Linguistics&lt;/em> (pp. 3214–3252). &lt;a href="https://doi.org/10.18653/v1/2022.acl-long.229" class="uri">https://doi.org/10.18653/v1/2022.acl-long.229&lt;/a>&lt;/p>
&lt;p>Louwerse, M. M. (2011). Symbol interdependency in symbolic and embodied cognition. &lt;em>Topics in Cognitive Science, 3&lt;/em>(2), 273–302. &lt;a href="https://doi.org/10.1111/j.1756-8765.2010.01106.x" class="uri">https://doi.org/10.1111/j.1756-8765.2010.01106.x&lt;/a>&lt;/p>
&lt;p>Louwerse, M., &amp;amp; Connell, L. (2011). A taste of words: Linguistic context and perceptual simulation predict the modality of words. &lt;em>Cognitive Science, 35&lt;/em>(2), 381–398. &lt;a href="https://doi.org/10.1111/j.1551-6709.2010.01157.x" class="uri">https://doi.org/10.1111/j.1551-6709.2010.01157.x&lt;/a>&lt;/p>
&lt;p>Louwerse, M. M., &amp;amp; Zwaan, R. A. (2009). Language encodes geographical information. &lt;em>Cognitive Science, 33&lt;/em>(1), 51–73. &lt;a href="https://doi.org/10.1111/j.1551-6709.2008.01003.x" class="uri">https://doi.org/10.1111/j.1551-6709.2008.01003.x&lt;/a>&lt;/p>
&lt;p>Lund, K., &amp;amp; Burgess, C. (1996). Producing high-dimensional semantic spaces from lexical co-occurrence. &lt;em>Behavior Research Methods, Instruments, &amp;amp; Computers, 28&lt;/em>(2), 203–208. &lt;a href="https://doi.org/10.3758/BF03204766" class="uri">https://doi.org/10.3758/BF03204766&lt;/a>&lt;/p>
&lt;p>Mikolov, T., Chen, K., Corrado, G., &amp;amp; Dean, J. (2013). Efficient estimation of word representations in vector space. &lt;em>arXiv&lt;/em>. &lt;a href="https://doi.org/10.48550/arXiv.1301.3781" class="uri">https://doi.org/10.48550/arXiv.1301.3781&lt;/a>&lt;/p>
&lt;p>Radford, A., Wu, J., Child, R., Luan, D., Amodei, D., &amp;amp; Sutskever, I. (2019). Language models are unsupervised multitask learners. &lt;em>OpenAI Blog&lt;/em>. &lt;a href="https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf" class="uri">https://cdn.openai.com/better-language-models/language_models_are_unsupervised_multitask_learners.pdf&lt;/a>&lt;/p>
&lt;p>Sclar, M., Choi, Y., Tsvetkov, Y., &amp;amp; Suhr, A. (2024). Quantifying language models’ sensitivity to spurious features in prompt design. In &lt;em>Proceedings of ICLR 2024&lt;/em>. &lt;a href="https://doi.org/10.48550/arXiv.2310.11324" class="uri">https://doi.org/10.48550/arXiv.2310.11324&lt;/a>&lt;/p>
&lt;p>Vaswani, A., Shazeer, N., Parmar, N., Uszkoreit, J., Jones, L., Gomez, A. N., Kaiser, Ł., &amp;amp; Polosukhin, I. (2017). Attention is all you need. In &lt;em>Advances in Neural Information Processing Systems&lt;/em> (Vol. 30). &lt;a href="https://doi.org/10.48550/arXiv.1706.03762" class="uri">https://doi.org/10.48550/arXiv.1706.03762&lt;/a>&lt;/p>
&lt;p>Wang, L., Chen, X., Deng, X., Wen, H., You, M., Liu, W., Li, Q., &amp;amp; Li, J. (2024). Prompt engineering in consistency and reliability with the evidence-based guideline for LLMs. &lt;em>NPJ Digital Medicine, 7&lt;/em>, Article 41. &lt;a href="https://doi.org/10.1038/s41746-024-01029-4" class="uri">https://doi.org/10.1038/s41746-024-01029-4&lt;/a>&lt;/p>
&lt;p>Wu, M., Conde, J., Reviriego, P., &amp;amp; Brysbaert, M. (2026). How does fine-tuning improve sensorimotor representations in large language models? &lt;em>arXiv&lt;/em>. &lt;a href="https://doi.org/10.48550/arXiv.2603.03313" class="uri">https://doi.org/10.48550/arXiv.2603.03313&lt;/a>&lt;/p>
&lt;p>Xu, Z., Jain, S., &amp;amp; Kankanhalli, M. (2024). Hallucination is inevitable: An innate limitation of large language models. &lt;em>arXiv&lt;/em>. &lt;a href="https://doi.org/10.48550/arXiv.2401.11817" class="uri">https://doi.org/10.48550/arXiv.2401.11817&lt;/a>&lt;/p>
&lt;p>Xu, Q., Peng, Y., Nastase, S. A., Chodorow, M., Wu, M., &amp;amp; Li, P. (2025). Large language models without grounding recover non-sensorimotor but not sensorimotor features of human concepts. &lt;em>Nature Human Behaviour, 9&lt;/em>(9), 1871–1886. &lt;a href="https://doi.org/10.1038/s41562-025-02203-8" class="uri">https://doi.org/10.1038/s41562-025-02203-8&lt;/a>&lt;/p>
&lt;/div></description><category>s</category><category>computational linguistics</category><category>word co-occurrence</category><category>machine learning</category><category>large language models</category><category>generative artificial intelligence</category><category>prompt engineering</category><category>OpenAI</category><category>Gemini</category><category>Claude</category><category>R</category><category>visualisation</category><category>large language models</category><category>R</category></item><item><title>R functions for checking and fixing vmrk files from BrainVision</title><link>https://pablobernabeu.github.io/2024/r-functions-for-checking-and-fixing-vmrk-files-from-brainvision/</link><pubDate>Sun, 30 Jun 2024 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2024/r-functions-for-checking-and-fixing-vmrk-files-from-brainvision/</guid><description>
&lt;p>Electroencephalography (EEG) has become a cornerstone for understanding the intricate workings of the human brain in the field of neuroscience. However, EEG software and hardware come with their own set of constraints, particularly in the management of markers, also known as triggers. This article aims to shed light on these limitations and future prospects of marker management in EEG studies, while also introducing R functions that can help deal with vmrk files from BrainVision.&lt;/p>
&lt;p>Markers, serving as timestamps that indicate specific events during data collection, play a crucial role in EEG studies. These events could range from the onset of a stimulus to the participant’s response. However, one of the major constraints in current EEG systems is the limitation of markers to numbers between 1 and 255. This limitation is due to the fact that markers are typically stored as 8-bit unsigned integers in computer memory, which can only represent numbers in the range of 0 to 255. However, the number 0 is usually reserved for system use, leaving only the numbers 1 to 255 available for markers.&lt;/p>
&lt;p>This numerical constraint can pose significant challenges in the interpretation of markers, especially in complex experimental designs where a multitude of events need to be marked and differentiated. It necessitates careful documentation of each marker’s purpose prior to running the study. This means that researchers must meticulously map each number to a specific event or condition in their experiment, which can be a daunting task, especially for complex studies with numerous conditions and events.&lt;/p>
&lt;p>Looking towards the future, one might wonder if it will become possible to send markers with semantic information, instead of being constrained to numbers between 1 and 255. This would allow researchers to encode more detailed information in each marker, such as the type of stimulus presented or the specific condition being tested. Such a development could revolutionize the way we conduct and analyze EEG studies, offering greater flexibility in experimental design and more nuanced insights into brain activity.&lt;/p>
&lt;p>Below, we’ll demonstrate some functions from &lt;a href="https://github.com/pablobernabeu/EEG-tools-and-tips">this GitHub repository&lt;/a> that help inspect and fix vmrk files. We’ll work with the vmrk file shown below.&lt;/p>
&lt;pre class="r">&lt;code># Read the file into a vector of lines
readLines(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/example.vmrk&amp;#39;)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## [1] &amp;quot;Brain Vision Data Exchange Marker File, Version 1.0&amp;quot;
## [2] &amp;quot;&amp;quot;
## [3] &amp;quot;[Common Infos]&amp;quot;
## [4] &amp;quot;DataFile=3.eeg&amp;quot;
## [5] &amp;quot;Codepage=utf-8&amp;quot;
## [6] &amp;quot;&amp;quot;
## [7] &amp;quot;[Marker Infos]&amp;quot;
## [8] &amp;quot;; Each entry: Mk&amp;lt;Marker number&amp;gt;=&amp;lt;Type&amp;gt;,&amp;lt;Description&amp;gt;,&amp;lt;Position in data points&amp;gt;,&amp;quot;
## [9] &amp;quot;; &amp;lt;Size in data points&amp;gt;, &amp;lt;Channel number (0 = marker is related to all channels)&amp;gt;,&amp;quot;
## [10] &amp;quot;; &amp;lt;Date (YYYYMMDDhhmmssuuuuuu)&amp;gt;&amp;quot;
## [11] &amp;quot;; Fields are delimited by commas, some fields might be omited (empty).&amp;quot;
## [12] &amp;quot;; Commas in type or description text are coded as \&amp;quot;\\1\&amp;quot;.&amp;quot;
## [13] &amp;quot;Mk1=New Segment,,1,1,0,20240318111955090000&amp;quot;
## [14] &amp;quot;Mk2=Stimulus,S254,20419,1,0&amp;quot;
## [15] &amp;quot;Mk3=Stimulus,S 5,22332,1,0&amp;quot;
## [16] &amp;quot;Mk4=Stimulus,S 42,23095,1,0&amp;quot;
## [17] &amp;quot;Mk5=Stimulus,S143,23100,1,0&amp;quot;
## [18] &amp;quot;Mk6=Stimulus,S 2,23106,1,0&amp;quot;
## [19] &amp;quot;Mk7=Stimulus,S102,23111,1,0&amp;quot;
## [20] &amp;quot;Mk8=Stimulus,S 6,25882,1,0&amp;quot;
## [21] &amp;quot;Mk9=Stimulus,S 5,28106,1,0&amp;quot;
## [22] &amp;quot;Mk10=Stimulus,S 50,29053,1,0&amp;quot;
## [23] &amp;quot;Mk11=Stimulus,S241,29058,1,0&amp;quot;
## [24] &amp;quot;Mk12=Stimulus,S 1,29063,1,0&amp;quot;
## [25] &amp;quot;Mk13=Stimulus,S101,29069,1,0&amp;quot;
## [26] &amp;quot;Mk14=Stimulus,S 6,31830,1,0&amp;quot;
## [27] &amp;quot;Mk15=Stimulus,S 5,34056,1,0&amp;quot;
## [28] &amp;quot;Mk16=Stimulus,S 49,35055,1,0&amp;quot;
## [29] &amp;quot;Mk17=Stimulus,S226,35060,1,0&amp;quot;
## [30] &amp;quot;Mk18=Stimulus,S 2,35066,1,0&amp;quot;
## [31] &amp;quot;Mk19=Stimulus,S103,35071,1,0&amp;quot;
## [32] &amp;quot;Mk20=Stimulus,S 6,37242,1,0&amp;quot;
## [33] &amp;quot;Mk21=Stimulus,S 5,39436,1,0&amp;quot;
## [34] &amp;quot;Mk22=Stimulus,S 43,40417,1,0&amp;quot;
## [35] &amp;quot;Mk23=Stimulus,S155,40423,1,0&amp;quot;
## [36] &amp;quot;Mk24=Stimulus,S 2,40429,1,0&amp;quot;
## [37] &amp;quot;Mk25=Stimulus,S103,40434,1,0&amp;quot;
## [38] &amp;quot;Mk26=Stimulus,S 6,42481,1,0&amp;quot;
## [39] &amp;quot;Mk27=Stimulus,S 5,44662,1,0&amp;quot;
## [40] &amp;quot;Mk28=Stimulus,S 40,45678,1,0&amp;quot;
## [41] &amp;quot;Mk29=Stimulus,S118,45683,1,0&amp;quot;
## [42] &amp;quot;Mk30=Stimulus,S 1,45688,1,0&amp;quot;
## [43] &amp;quot;Mk31=Stimulus,S103,45693,1,0&amp;quot;
## [44] &amp;quot;Mk32=Stimulus,S 6,47621,1,0&amp;quot;
## [45] &amp;quot;Mk33=Stimulus,S 5,49809,1,0&amp;quot;
## [46] &amp;quot;Mk34=Stimulus,S 50,50808,1,0&amp;quot;
## [47] &amp;quot;Mk35=Stimulus,S237,50813,1,0&amp;quot;
## [48] &amp;quot;Mk36=Stimulus,S 3,50818,1,0&amp;quot;
## [49] &amp;quot;Mk37=Stimulus,S101,50823,1,0&amp;quot;
## [50] &amp;quot;Mk38=Stimulus,S 6,53823,1,0&amp;quot;
## [51] &amp;quot;Mk39=Stimulus,S 5,56042,1,0&amp;quot;
## [52] &amp;quot;Mk40=Stimulus,S 40,57129,1,0&amp;quot;
## [53] &amp;quot;Mk41=Stimulus,S114,57134,1,0&amp;quot;
## [54] &amp;quot;Mk42=Stimulus,S 3,57140,1,0&amp;quot;
## [55] &amp;quot;Mk43=Stimulus,S103,57145,1,0&amp;quot;
## [56] &amp;quot;Mk44=Stimulus,S 6,59661,1,0&amp;quot;&lt;/code>&lt;/pre>
&lt;div id="numbering-trials" class="section level2">
&lt;h2>Numbering trials&lt;/h2>
&lt;p>The antediluvian limitation of markers often prevents us from storing the order of trials using markers. Thus, when we need to inspect or fix vmrk files, we must mentally divide the lines into trials. For instance, in our example vmrk file, all trials begin with the marker &lt;code>S 5&lt;/code>. The function below allows us to temporarily number trials by appending the number to the first marker of each trial. The parameters of the function allow us to select the &lt;code>start_line&lt;/code> to skip the metadata at the top of the vmrk file, as well as to select the number of &lt;code>lines_per_trial&lt;/code> and the &lt;code>first_number&lt;/code> to use in the first trial.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FEEG-tools-and-tips%2Fblob%2Fmain%2Fnumber_trials.R%23L3-L24&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;pre class="r">&lt;code># Create temporary vmrk file with numbered trials
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/number_trials.R&amp;#39;)
number_trials(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/example.vmrk&amp;#39;,
start_line = 15, lines_per_trial = 6, first_number = 1)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## [1] &amp;quot;Brain Vision Data Exchange Marker File, Version 1.0&amp;quot;
## [2] &amp;quot;&amp;quot;
## [3] &amp;quot;[Common Infos]&amp;quot;
## [4] &amp;quot;DataFile=3.eeg&amp;quot;
## [5] &amp;quot;Codepage=utf-8&amp;quot;
## [6] &amp;quot;&amp;quot;
## [7] &amp;quot;[Marker Infos]&amp;quot;
## [8] &amp;quot;; Each entry: Mk&amp;lt;Marker number&amp;gt;=&amp;lt;Type&amp;gt;,&amp;lt;Description&amp;gt;,&amp;lt;Position in data points&amp;gt;,&amp;quot;
## [9] &amp;quot;; &amp;lt;Size in data points&amp;gt;, &amp;lt;Channel number (0 = marker is related to all channels)&amp;gt;,&amp;quot;
## [10] &amp;quot;; &amp;lt;Date (YYYYMMDDhhmmssuuuuuu)&amp;gt;&amp;quot;
## [11] &amp;quot;; Fields are delimited by commas, some fields might be omited (empty).&amp;quot;
## [12] &amp;quot;; Commas in type or description text are coded as \&amp;quot;\\1\&amp;quot;.&amp;quot;
## [13] &amp;quot;Mk1=New Segment,,1,1,0,20240318111955090000&amp;quot;
## [14] &amp;quot;Mk2=Stimulus,S254,20419,1,0&amp;quot;
## [15] &amp;quot;Mk3=Stimulus,S 5,22332,1,0 1&amp;quot;
## [16] &amp;quot;Mk4=Stimulus,S 42,23095,1,0&amp;quot;
## [17] &amp;quot;Mk5=Stimulus,S143,23100,1,0&amp;quot;
## [18] &amp;quot;Mk6=Stimulus,S 2,23106,1,0&amp;quot;
## [19] &amp;quot;Mk7=Stimulus,S102,23111,1,0&amp;quot;
## [20] &amp;quot;Mk8=Stimulus,S 6,25882,1,0&amp;quot;
## [21] &amp;quot;Mk9=Stimulus,S 5,28106,1,0 2&amp;quot;
## [22] &amp;quot;Mk10=Stimulus,S 50,29053,1,0&amp;quot;
## [23] &amp;quot;Mk11=Stimulus,S241,29058,1,0&amp;quot;
## [24] &amp;quot;Mk12=Stimulus,S 1,29063,1,0&amp;quot;
## [25] &amp;quot;Mk13=Stimulus,S101,29069,1,0&amp;quot;
## [26] &amp;quot;Mk14=Stimulus,S 6,31830,1,0&amp;quot;
## [27] &amp;quot;Mk15=Stimulus,S 5,34056,1,0 3&amp;quot;
## [28] &amp;quot;Mk16=Stimulus,S 49,35055,1,0&amp;quot;
## [29] &amp;quot;Mk17=Stimulus,S226,35060,1,0&amp;quot;
## [30] &amp;quot;Mk18=Stimulus,S 2,35066,1,0&amp;quot;
## [31] &amp;quot;Mk19=Stimulus,S103,35071,1,0&amp;quot;
## [32] &amp;quot;Mk20=Stimulus,S 6,37242,1,0&amp;quot;
## [33] &amp;quot;Mk21=Stimulus,S 5,39436,1,0 4&amp;quot;
## [34] &amp;quot;Mk22=Stimulus,S 43,40417,1,0&amp;quot;
## [35] &amp;quot;Mk23=Stimulus,S155,40423,1,0&amp;quot;
## [36] &amp;quot;Mk24=Stimulus,S 2,40429,1,0&amp;quot;
## [37] &amp;quot;Mk25=Stimulus,S103,40434,1,0&amp;quot;
## [38] &amp;quot;Mk26=Stimulus,S 6,42481,1,0&amp;quot;
## [39] &amp;quot;Mk27=Stimulus,S 5,44662,1,0 5&amp;quot;
## [40] &amp;quot;Mk28=Stimulus,S 40,45678,1,0&amp;quot;
## [41] &amp;quot;Mk29=Stimulus,S118,45683,1,0&amp;quot;
## [42] &amp;quot;Mk30=Stimulus,S 1,45688,1,0&amp;quot;
## [43] &amp;quot;Mk31=Stimulus,S103,45693,1,0&amp;quot;
## [44] &amp;quot;Mk32=Stimulus,S 6,47621,1,0&amp;quot;
## [45] &amp;quot;Mk33=Stimulus,S 5,49809,1,0 6&amp;quot;
## [46] &amp;quot;Mk34=Stimulus,S 50,50808,1,0&amp;quot;
## [47] &amp;quot;Mk35=Stimulus,S237,50813,1,0&amp;quot;
## [48] &amp;quot;Mk36=Stimulus,S 3,50818,1,0&amp;quot;
## [49] &amp;quot;Mk37=Stimulus,S101,50823,1,0&amp;quot;
## [50] &amp;quot;Mk38=Stimulus,S 6,53823,1,0&amp;quot;
## [51] &amp;quot;Mk39=Stimulus,S 5,56042,1,0 7&amp;quot;
## [52] &amp;quot;Mk40=Stimulus,S 40,57129,1,0&amp;quot;
## [53] &amp;quot;Mk41=Stimulus,S114,57134,1,0&amp;quot;
## [54] &amp;quot;Mk42=Stimulus,S 3,57140,1,0&amp;quot;
## [55] &amp;quot;Mk43=Stimulus,S103,57145,1,0&amp;quot;
## [56] &amp;quot;Mk44=Stimulus,S 6,59661,1,0&amp;quot;&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="removing-trial-numbers" class="section level2">
&lt;h2>Removing trial numbers&lt;/h2>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FEEG-tools-and-tips%2Fblob%2Fmain%2Fremove_trial_numbers.R%23L3-L20&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>Now, we will unnumber the trials. This can be especially useful after fixing any errors in the markers. For this demo, we’ll use an &lt;a href="https://github.com/pablobernabeu/EEG-tools-and-tips/blob/main/example_numbered_trials.vmrk">example file with numbered trials&lt;/a> that looks just like the output from &lt;code>number_trials()&lt;/code> shown above.&lt;/p>
&lt;pre class="r">&lt;code># Remove trial numbers from temporary vmrk file
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/remove_trial_numbers.R&amp;#39;)
remove_trial_numbers(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/example_numbered_trials.vmrk&amp;#39;)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## [1] &amp;quot;Brain Vision Data Exchange Marker File, Version 1.0&amp;quot;
## [2] &amp;quot;&amp;quot;
## [3] &amp;quot;[Common Infos]&amp;quot;
## [4] &amp;quot;DataFile=3.eeg&amp;quot;
## [5] &amp;quot;Codepage=utf-8&amp;quot;
## [6] &amp;quot;&amp;quot;
## [7] &amp;quot;[Marker Infos]&amp;quot;
## [8] &amp;quot;; Each entry: Mk&amp;lt;Marker number&amp;gt;=&amp;lt;Type&amp;gt;,&amp;lt;Description&amp;gt;,&amp;lt;Position in data points&amp;gt;,&amp;quot;
## [9] &amp;quot;; &amp;lt;Size in data points&amp;gt;, &amp;lt;Channel number (0 = marker is related to all channels)&amp;gt;,&amp;quot;
## [10] &amp;quot;; &amp;lt;Date (YYYYMMDDhhmmssuuuuuu)&amp;gt;&amp;quot;
## [11] &amp;quot;; Fields are delimited by commas, some fields might be omited (empty).&amp;quot;
## [12] &amp;quot;; Commas in type or description text are coded as \&amp;quot;\\1\&amp;quot;.&amp;quot;
## [13] &amp;quot;Mk1=New Segment,,1,1,0,20240318111955090000&amp;quot;
## [14] &amp;quot;Mk2=Stimulus,S254,20419,1,0&amp;quot;
## [15] &amp;quot;Mk3=Stimulus,S 5,22332,1,0&amp;quot;
## [16] &amp;quot;Mk4=Stimulus,S 42,23095,1,0&amp;quot;
## [17] &amp;quot;Mk5=Stimulus,S143,23100,1,0&amp;quot;
## [18] &amp;quot;Mk6=Stimulus,S 2,23106,1,0&amp;quot;
## [19] &amp;quot;Mk7=Stimulus,S102,23111,1,0&amp;quot;
## [20] &amp;quot;Mk8=Stimulus,S 6,25882,1,0&amp;quot;
## [21] &amp;quot;Mk9=Stimulus,S 5,28106,1,0&amp;quot;
## [22] &amp;quot;Mk10=Stimulus,S 50,29053,1,0&amp;quot;
## [23] &amp;quot;Mk11=Stimulus,S241,29058,1,0&amp;quot;
## [24] &amp;quot;Mk12=Stimulus,S 1,29063,1,0&amp;quot;
## [25] &amp;quot;Mk13=Stimulus,S101,29069,1,0&amp;quot;
## [26] &amp;quot;Mk14=Stimulus,S 6,31830,1,0&amp;quot;
## [27] &amp;quot;Mk15=Stimulus,S 5,34056,1,0&amp;quot;
## [28] &amp;quot;Mk16=Stimulus,S 49,35055,1,0&amp;quot;
## [29] &amp;quot;Mk17=Stimulus,S226,35060,1,0&amp;quot;
## [30] &amp;quot;Mk18=Stimulus,S 2,35066,1,0&amp;quot;
## [31] &amp;quot;Mk19=Stimulus,S103,35071,1,0&amp;quot;
## [32] &amp;quot;Mk20=Stimulus,S 6,37242,1,0&amp;quot;
## [33] &amp;quot;Mk21=Stimulus,S 5,39436,1,0&amp;quot;
## [34] &amp;quot;Mk22=Stimulus,S 43,40417,1,0&amp;quot;
## [35] &amp;quot;Mk23=Stimulus,S155,40423,1,0&amp;quot;
## [36] &amp;quot;Mk24=Stimulus,S 2,40429,1,0&amp;quot;
## [37] &amp;quot;Mk25=Stimulus,S103,40434,1,0&amp;quot;
## [38] &amp;quot;Mk26=Stimulus,S 6,42481,1,0&amp;quot;
## [39] &amp;quot;Mk27=Stimulus,S 5,44662,1,0&amp;quot;
## [40] &amp;quot;Mk28=Stimulus,S 40,45678,1,0&amp;quot;
## [41] &amp;quot;Mk29=Stimulus,S118,45683,1,0&amp;quot;
## [42] &amp;quot;Mk30=Stimulus,S 1,45688,1,0&amp;quot;
## [43] &amp;quot;Mk31=Stimulus,S103,45693,1,0&amp;quot;
## [44] &amp;quot;Mk32=Stimulus,S 6,47621,1,0&amp;quot;
## [45] &amp;quot;Mk33=Stimulus,S 5,49809,1,0&amp;quot;
## [46] &amp;quot;Mk34=Stimulus,S 50,50808,1,0&amp;quot;
## [47] &amp;quot;Mk35=Stimulus,S237,50813,1,0&amp;quot;
## [48] &amp;quot;Mk36=Stimulus,S 3,50818,1,0&amp;quot;
## [49] &amp;quot;Mk37=Stimulus,S101,50823,1,0&amp;quot;
## [50] &amp;quot;Mk38=Stimulus,S 6,53823,1,0&amp;quot;
## [51] &amp;quot;Mk39=Stimulus,S 5,56042,1,0&amp;quot;
## [52] &amp;quot;Mk40=Stimulus,S 40,57129,1,0&amp;quot;
## [53] &amp;quot;Mk41=Stimulus,S114,57134,1,0&amp;quot;
## [54] &amp;quot;Mk42=Stimulus,S 3,57140,1,0&amp;quot;
## [55] &amp;quot;Mk43=Stimulus,S103,57145,1,0&amp;quot;
## [56] &amp;quot;Mk44=Stimulus,S 6,59661,1,0&amp;quot;&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="counting-markers" class="section level2">
&lt;h2>Counting markers&lt;/h2>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FEEG-tools-and-tips%2Fblob%2Fmain%2Fcount_markers.R%23L3-L18&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;pre class="r">&lt;code>source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/count_markers.R&amp;#39;)
count_markers(file = &amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/example.vmrk&amp;#39;,
marker = &amp;#39;S 2&amp;#39;)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## Count of &amp;quot;S 2&amp;quot;: 3 instances&lt;/code>&lt;/pre>
&lt;pre class="r">&lt;code>count_markers(file = &amp;#39;https://raw.githubusercontent.com/pablobernabeu/EEG-tools-and-tips/main/example.vmrk&amp;#39;,
marker = &amp;#39;S 3&amp;#39;)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## Count of &amp;quot;S 3&amp;quot;: 2 instances&lt;/code>&lt;/pre>
&lt;/div></description><category>research methods</category><category>electroencephalography</category><category>EEG</category><category>BrainVision</category><category>event-related potentials</category><category>s</category><category>research methods</category><category>R</category></item><item><title>rscopus_plus: An extension of the rscopus package</title><link>https://pablobernabeu.github.io/2024/rscopus-plus-an-extension-of-the-rscopus-package/</link><pubDate>Wed, 21 Feb 2024 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2024/rscopus-plus-an-extension-of-the-rscopus-package/</guid><description>
&lt;p>Sometimes it’s useful to do a bibliometric analysis. To this end, the &lt;a href="https://github.com/pablobernabeu/rscopus_plus">&lt;code>rscopus_plus&lt;/code>&lt;/a> functions (Bernabeu, 2024) extend the R package &lt;a href="https://github.com/muschellij2/rscopus">&lt;code>rscopus&lt;/code>&lt;/a> (Muschelli, 2022) to administer the search quota and enable specific searches and comparisons.&lt;/p>
&lt;ul>
&lt;li>&lt;p>&lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/scopus_search_plus.R">&lt;code>scopus_search_plus&lt;/code>&lt;/a> runs &lt;code>rscopus::scopus_search&lt;/code> as many times as necessary based on the number of results and the search quota.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/scopus_search_DOIs.R">&lt;code>scopus_search_DOIs&lt;/code>&lt;/a> gets DOIs from &lt;code>scopus_search_plus&lt;/code>, which can then be imported into a reference manager, such as Zotero, to create a list of references.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/scopus_search_additional_DOIs.R">&lt;code>scopus_search_additional_DOIs&lt;/code>&lt;/a> searches for additional DOIs.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/scopus_comparison.R">&lt;code>scopus_comparison&lt;/code>&lt;/a> compares counts of publications on various topics throughout a certain period. The comparison terms are shown in the legend and in the lines, and they all include the reference query.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/plot_scopus_comparison.R">&lt;code>plot_scopus_comparison&lt;/code>&lt;/a> draws a line plot with the output from &lt;code>scopus_comparison&lt;/code>.&lt;/p>&lt;/li>
&lt;/ul>
&lt;div class="alert alert-warning" role="alert" style="padding-bottom: 0; margin-top: 3%; margin-bottom: 4%;">
&lt;p>&lt;em>Note.&lt;/em> Before using any of the first four functions, the user must set their Scopus API key confidentially (see &lt;a href="https://cran.r-project.org/web/packages/rscopus/vignettes/api_key.html">rscopus guidelines&lt;/a>).&lt;/p>
&lt;/div>
&lt;div id="example-of-use" class="section level2">
&lt;h2>Example of use&lt;/h2>
&lt;p>As an example (also available &lt;a href="https://github.com/pablobernabeu/L2_L3_EF/blob/main/biblio_analysis.R">on GitHub&lt;/a>), we’ll visualise the prevalence of three executive functions in the literatures on second and third language throughout the past two decades.&lt;/p>
&lt;p>First, we’ll use &lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/scopus_comparison.R">&lt;code>scopus_comparison()&lt;/code>&lt;/a> (fragment shown below).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Frscopus_plus%2Fblob%2Fmain%2Fscopus_comparison.R%23L2-L23&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>Next, we’ll use &lt;a href="https://github.com/pablobernabeu/rscopus_plus/blob/main/plot_scopus_comparison.R">&lt;code>plot_scopus_comparison()&lt;/code>&lt;/a> (fragment shown below).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Frscopus_plus%2Fblob%2Fmain%2Fplot_scopus_comparison.R%23L4-L14&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;pre class="r">&lt;code>library(rscopus)
# set_api_key(&amp;#39;your_key_here&amp;#39;) # (see https://cran.r-project.org/web/packages/rscopus/vignettes/api_key.html)
# I&amp;#39;ll read in my personal Scopus key from a file.
# If you do this, make sure not to share your file.
api_key = readLines(&amp;#39;scopus_key.txt&amp;#39;)
set_api_key(api_key)
library(dplyr)
library(patchwork)
# Load in Scopus search functions from https://github.com/pablobernabeu/rscopus_plus
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/rscopus_plus/main/scopus_comparison.R&amp;#39;)
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/rscopus_plus/main/plot_scopus_comparison.R&amp;#39;)
# General parameters
search_period = 1990:2023
quota = 20
# Prevalence of three executive functions in second language studies from 2000 to 2023.
# In addition to &amp;quot;second language&amp;quot;, the reference query includes the terms
# &amp;quot;learning&amp;quot; and &amp;quot;cognition&amp;quot; to make the scope of the search more relevant to
# the topic of interest.
reference_query = &amp;#39;&amp;quot;second language&amp;quot;&amp;#39;
comparison_terms = c( &amp;#39;&amp;quot;working memory&amp;quot;&amp;#39;, &amp;#39;inhibit*&amp;#39;, &amp;#39;&amp;quot;implicit learning&amp;quot;&amp;#39; )
N_comparison_terms = length(comparison_terms)
L2_EF =
scopus_comparison(reference_query, comparison_terms,
search_period, quota, verbose = FALSE,
reference_query_field_tag = &amp;#39;TITLE-ABS-KEY&amp;#39;)
saveRDS(L2_EF, &amp;#39;L2_EF.rds&amp;#39;)
L2_EF = readRDS(&amp;#39;L2_EF.rds&amp;#39;) # it&amp;#39;s possible to load results directly
plot_L2_EF =
plot_scopus_comparison(L2_EF,
pub_count_in_legend = FALSE,
pub_count_in_lines = TRUE) +
scale_color_manual(
values = c( &amp;quot;[ref.] + &amp;#39;\&amp;quot;working memory\&amp;quot;&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[1],
&amp;quot;[ref.] + &amp;#39;inhibit*&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[2],
&amp;quot;[ref.] + &amp;#39;\&amp;quot;implicit learning\&amp;quot;&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[3] )
) +
guides(colour = guide_legend(override.aes = list(alpha = 1))) +
# Prepare layout for the multi-plot combination
theme(axis.text.x = element_blank(), axis.title.x = element_blank(),
legend.position = &amp;#39;none&amp;#39;, plot.margin = margin(0, 0, 15, 0))
# Prevalence of three executive functions in third language studies from 2000 to 2023.
# In addition to &amp;quot;third language&amp;quot;, the reference query includes the terms &amp;quot;learning&amp;quot;
# and &amp;quot;cognition&amp;quot; to make the scope of the search more relevant to the topic of
# interest.
reference_query = &amp;#39;&amp;quot;third language&amp;quot;&amp;#39;
# Other parameters identical to those used in the query above.
L3_EF =
scopus_comparison(reference_query, comparison_terms,
search_period, quota, verbose = FALSE,
reference_query_field_tag = &amp;#39;TITLE-ABS-KEY&amp;#39;)
saveRDS(L3_EF, &amp;#39;L3_EF.rds&amp;#39;)
L3_EF = readRDS(&amp;#39;L3_EF.rds&amp;#39;) # it&amp;#39;s possible to load results directly
plot_L3_EF =
plot_scopus_comparison(L3_EF,
pub_count_in_legend = FALSE,
pub_count_in_lines = TRUE) +
scale_color_manual(
values = c( &amp;quot;[ref.] + &amp;#39;\&amp;quot;working memory\&amp;quot;&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[1],
&amp;quot;[ref.] + &amp;#39;inhibit*&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[2],
&amp;quot;[ref.] + &amp;#39;\&amp;quot;implicit learning\&amp;quot;&amp;#39;&amp;quot; = scales::hue_pal()(N_comparison_terms)[3] )
) +
guides(colour = guide_legend(override.aes = list(alpha = 1))) +
# Prepare layout for the multi-plot combination
theme(axis.text.x = element_text(margin = margin(7, 0, 0, 0, &amp;#39;pt&amp;#39;)),
axis.title.x = element_text(margin = margin(8, 0, 0, 0, &amp;#39;pt&amp;#39;)),
legend.position = &amp;#39;inside&amp;#39;, legend.position.inside = c(.82, .8))
# Combine plots
plot_L2_EF + plot_L3_EF +
plot_layout(ncol = 1, axes = &amp;#39;collect&amp;#39;) &amp;amp;
theme(axis.text = element_text(size = 10),
axis.title = element_text(vjust = 0.5, size = 13),
plot.title = element_markdown(hjust = 0.5, size = 12),
legend.text = element_text(size = 11,),
legend.background = element_rect(color = &amp;#39;grey80&amp;#39;, fill = &amp;#39;grey99&amp;#39;),
legend.margin = margin(0, 5, 2, 0)) &lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2024/rscopus-plus-an-extension-of-the-rscopus-package/index.en_files/figure-html/unnamed-chunk-1-1.png" width="720" alt="Two line charts of yearly publication percentages for working memory, inhibition and implicit learning, relative to second language and third language queries" />&lt;/p>
&lt;p>The total number of publications over the current period is shown between brackets after each query.&lt;/p>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2024). &lt;em>rscopus_plus&lt;/em>. OSF. &lt;a href="https://doi.org/10.17605/OSF.IO/BUZQ6" class="uri">https://doi.org/10.17605/OSF.IO/BUZQ6&lt;/a>&lt;/p>
&lt;p>Muschelli, J. (2022). &lt;em>Package ’rscopus’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/rscopus/rscopus.pdf" class="uri">https://cran.r-project.org/web/packages/rscopus/rscopus.pdf&lt;/a>&lt;/p>
&lt;/div></description><category>bibliometrics</category><category>R</category><category>research methods</category><category>research software</category><category>second language</category><category>third language</category><category>Executive functions</category><category>working memory</category><category>inhibition</category><category>implicit learning</category><category>s</category><category>R</category><category>bibliometrics</category></item><item><title>FAQs on mixed-effects models</title><link>https://pablobernabeu.github.io/2023/faqs-on-mixed-effects-models/</link><pubDate>Sat, 04 Nov 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/faqs-on-mixed-effects-models/</guid><description>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>I am dealing with nested data, and I remember from an article by &lt;a href="https://doi.org/10.1016/S0022-5371(73)80014-3">Clark (1973)&lt;/a> that nested should be analysed using special models. I’ve looked into mixed-effects models, and I’ve reached a structure with random intercepts by subjects and by items. Is this fine?&lt;/p>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>In early days, researchers would aggregate the data across these repeated measures to prevent the violation of the assumption of independence of observations, which is one of the most important assumptions in statistics. With the advent of mixed-effects models, researchers began accounting for these repeated measures using random intercepts and slopes. However, problems of convergence led many researchers to remove random slopes. This became widespread until, over the past few years, we have realised that random slopes are necessary to prevent an inflation of the Type I error due to the violation of the assumption of independence (&lt;a href="https://psych.wisc.edu/Brauer/BrauerLab/wp-content/uploads/2014/04/Brauer-Curtin-2018-on-LMEMs.pdf">Brauer &amp;amp; Curtin, 2018&lt;/a>; &lt;a href="http://singmann.org/download/publications/singmann_kellen-introduction-mixed-models.pdf">Singmann &amp;amp; Kellen, 2019&lt;/a>). Please see Table 17 in Brauer and Curtin (2018). Due to the present reasons, the models in the current article are anti-conservative. To redress this problem, please consider the inclusion of random slopes by participant for all between-items variables [e.g., &lt;code>(stimulus_condition | participant)&lt;/code>], and random slopes by item for all between-participants variables [e.g., &lt;code>(extraversion | item)&lt;/code>]. Interaction terms should also have the corresponding slopes, except when the variables in the interaction vary within different units, that is, one between participants and one between items (&lt;a href="https://psych.wisc.edu/Brauer/BrauerLab/wp-content/uploads/2014/04/Brauer-Curtin-2018-on-LMEMs.pdf">Brauer &amp;amp; Curtin, 2018&lt;/a>). Each of the random intercepts and random slopes included in the model should be noted in the main text, for instance using footnotes in the results table (see &lt;a href="https://bookdown.org/pablobernabeu/language-sensorimotor-conceptual-processing-statistical-power/study-2.1-semantic-priming.html#semanticpriming-results">example&lt;/a>).&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>I calculated the &lt;em>p&lt;/em> values by comparing minimally-different models using the &lt;code>anova&lt;/code> function. Is this fine?&lt;/p>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>&lt;a href="https://doi.org/10.3758/s13428-016-0809-y">Luke (2017)&lt;/a> warns that the &lt;em>p&lt;/em> values calculated by model comparison—which are based on likelihood ratio tests—can be anti-conservative. Therefore, the Kenward-Roger and the Satterthwaite methods are recommended instead (both available in other packages, such as &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">lmerTest&lt;/a> and &lt;a href="https://cran.r-project.org/web/packages/afex/afex.pdf">afex&lt;/a>).&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>The lme4 package only runs on one thread (CPU) but the computer has 8. Do you have any advice on making the model run using more of the threads? It’s taking a very long time. I’ve seen these two possible solutions online from 2018 (&lt;a href="https://stackoverflow.com/questions/48315268/how-can-i-make-r-using-more-than-1-core-8-available-on-a-ubuntu-rstudio-server">here&lt;/a> and &lt;a href="https://stat.ethz.ch/pipermail/r-sig-mixed-models/2018q3/027170.html">here&lt;/a>) but would like some advice if they have any or have attempted either of these solutions.&lt;/p>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>From the information I have seen in the past as well as right now, parallelising (g)lmer intentionally would be very involved. There is certainly interest in it, as your resources show (also see &lt;a href="https://github.com/lme4/lme4/issues?q=is%3Aissue+parallel">here&lt;/a>). However, the current information suggests to me that it is not possible.&lt;/p>
&lt;p>Interestingly, some isolated cases of unintentional parallelisation have been documented, and the developers of the &lt;a href="https://cran.r-project.org/web/packages/lme4/lme4.pdf">lme4&lt;/a> package were &lt;a href="">surprised about them&lt;/a> because they have not created this feature (see &lt;a href="https://github.com/lme4/lme4/issues/492">here&lt;/a> and &lt;a href="https://github.com/lme4/lme4/issues/627">here&lt;/a>).&lt;/p>
&lt;p>I think the best approach may be running your model(s) in a high-performance computing (HPC) cluster. Although this would not reduce the amount of time required for each model, it would have two advantages. First, your own computers wouldn’t be busy for days, and second, you could even run several models at the same time without exhausting your own computers. I still have access to the HPC at my previous university, and it would be fine for me to send your model(s) there if that would help you. Feel free to let me know. Otherwise I can see that your university has this facility too.&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>We took your advice and ran the model on a supercomputer - it took roughly 2.5 days, which is what it took for the model to run on my iMac and a gaming laptop Vivienne has.&lt;/p>
&lt;p>The model, however, didn’t converge. We have read that you can use &lt;code>allFit()&lt;/code> to try the fit with all available optimizers. Do you have any experience using this? If you did, I wondered where this would sit in the code for the model? How and where do I add this in to check all available optimizers, please?&lt;/p>
&lt;p>I have attached my code in a txt file and the data in excel for you to see, in case it is of any use.&lt;/p>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>The multi-optimizer check is indeed a way (albeit tentative) to probe into the convergence. Convergence has long been a fuzzy subject, as there are different standpoints depending on the degree of conservativeness that is sought after by the analysts.&lt;/p>
&lt;p>On Page 124 in my thesis (&lt;a href="https://osf.io/97u5c" class="uri">https://osf.io/97u5c&lt;/a>), you can find this multi-optimizer check (also see this &lt;a href="https://pablobernabeu.github.io/2021/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit">blog post&lt;/a>). All the code is available on OSF. More generally, I discuss the issue of convergence throughout the thesis.&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>I have run the model with &lt;code>optimizer="nloptwrap"&lt;/code> and &lt;code>algorithm="NLOPT_LN_BOBYQA"&lt;/code> and received the following warning message (once the model ran) -&lt;/p>
&lt;pre>&lt;code>In optwrap(optimizer, devfun, start, rho$lower, control = control, :
convergence code 5 from nloptwrap: NLOPT_MAXEVAL_REACHED: optimization stopped because maxeval (above) was reached.&lt;/code>&lt;/pre>
&lt;p>Does this mean that the model didn’t converge? I’m only asking because I wasn’t given a statement saying it didn’t converge, as it did with Nelder_Mead. It was stated (at the end of summary table)&lt;/p>
&lt;pre>&lt;code>Optimizer (Nelder_Mead) convergence code: 4 (failure to converge in 10000 evaluations)
failure to converge in 10000 evaluations&lt;/code>&lt;/pre>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>Please try &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/semanticpriming_lmerTest.R#L109">increasing the max number of iterations&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;blockquote style="color: black; background-color: #FFF9F3; margin-bottom: 30px;">
&lt;p>We increased the max number of iterations to 1e6 and then 1e7, and the model didn’t converge. But it has converged with &lt;code>maxeval=1e8&lt;/code>.&lt;/p>
&lt;p>I wanted to ask please, do you know of any issues with the max iterations being this high and effecting the interpretability of the model? Or is it completely fine?&lt;/p>
&lt;/blockquote>
&lt;div style="padding-left: 60px;">
&lt;blockquote style="color: black; background-color: #F4FFF3; margin-bottom: 55px;">
&lt;p>There are no side-effects to increasing the number of iterations (see Remedy 6 in &lt;a href="https://psych.wisc.edu/Brauer/BrauerLab/wp-content/uploads/2014/04/Brauer-Curtin-2018-on-LMEMs.pdf">Brauer &amp;amp; Curtin, 2018&lt;/a>).&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Brauer, M., &amp;amp; Curtin, L. A. (2018). Mixed models in psychology: An introduction to the world of multilevel models. &lt;em>Psychological Methods, 23&lt;/em>(3), 389-411. &lt;a href="https://doi.org/10.1037/met0000132" class="uri">https://doi.org/10.1037/met0000132&lt;/a>&lt;/p>
&lt;p>Clark, H. H. (1973). The language-as-fixed-effect fallacy: A critique of language statistics in psychological research. &lt;em>Journal of Verbal Learning and Verbal Behavior, 12&lt;/em>(4), 335-359. &lt;a href="https://doi.org/10.1016/S0022-5371(73)80014-3" class="uri">https://doi.org/10.1016/S0022-5371(73)80014-3&lt;/a>&lt;/p>
&lt;p>Luke, S. G. (2017). Evaluating significance in linear mixed-effects models in R. &lt;em>Behavior Research Methods, 49&lt;/em>(4), 1494–1502. &lt;a href="https://doi.org/10.3758/s13428-016-0809-y" class="uri">https://doi.org/10.3758/s13428-016-0809-y&lt;/a>&lt;/p>
&lt;p>Singmann, H., &amp;amp; Kellen, D. (2019). An introduction to mixed models for experimental psychology. In D. H. Spieler &amp;amp; E. Schumacher (Eds.), &lt;em>New Methods in Cognitive Psychology&lt;/em> (pp. 4–31). Hove, UK: Psychology Press. &lt;a href="http://singmann.org/download/publications/singmann_kellen-introduction-mixed-models.pdf" class="uri">http://singmann.org/download/publications/singmann_kellen-introduction-mixed-models.pdf&lt;/a>&lt;/p>
&lt;/div></description><category>linear-mixed effects models</category><category>R</category><category>research methods</category><category>s</category><category>linear mixed-effects models</category><category>R</category></item><item><title>FAIR standards for the creation of research materials, with examples</title><link>https://pablobernabeu.github.io/2023/fair-standards-for-the-creation-of-research-materials-with-examples/</link><pubDate>Thu, 02 Nov 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/fair-standards-for-the-creation-of-research-materials-with-examples/</guid><description>
&lt;div class="alert alert-info" role="alert" style="padding-bottom: 0; margin-bottom: 4%;">
&lt;p>In the fast-paced world of scientific research, establishing minimum standards for the creation of research materials is essential. Whether it’s stimuli, custom software for data collection, or scripts for statistical analysis, the quality and transparency of these materials significantly impact the reproducibility and credibility of research. This blog post explores the importance of adhering to FAIR (Findable, Accessible, Interoperable, Reusable) principles, and offers practical examples for researchers, with a focus on the cognitive sciences.&lt;/p>
&lt;/div>
&lt;p>Notwithstanding the need for speed in most scientific projects, what should be the &lt;strong>minimum acceptable standards&lt;/strong> in the &lt;strong>creation of research materials&lt;/strong> such as stimuli, custom software for data collection (e.g., experiment in jsPsych, OpenSesame or psychoPy), or scripts for statistical analysis?&lt;/p>
&lt;p>The answer to this question is contingent upon the field of research, the purpose and the duration of the project, and many other contextual factors. So, to narrow down the scope and come at a general answer, let’s suppose we asked a researcher in the cognitive sciences (e.g., a linguist, a psychologist or a neuroscientist) who values open science. Perhaps, such a researchers would be satisfied with a method for the creation of materials that &lt;strong>allows the creators of the materials, as well as their collaborators and any other stakeholders (e.g., any fellow scientists working in the same field), to explore, understand, reproduce, modify, and reuse the materials following their completion and thereafter&lt;/strong>. Let’s review some of the implements that can help fulfil these standards.&lt;/p>
&lt;div id="fairness" class="section level1">
&lt;h1>FAIRness&lt;/h1>
&lt;p>The &lt;a href="https://www.go-fair.org/fair-principles">FAIR Guiding Principles for scientific data management and stewardship&lt;/a> exhaustively describe a protocol for making materials &lt;b>F&lt;/b>indable, &lt;b>A&lt;/b>ccessible, &lt;b>I&lt;/b>nteroperable and &lt;b>R&lt;/b>eusable. These terms cover the five allowances listed above, along with other important aspects.&lt;/p>
&lt;p>Let’s look at some instantiations of the FAIR principles.&lt;/p>
&lt;div id="sharing-the-materials" class="section level2">
&lt;h2>Sharing the materials&lt;/h2>
&lt;p>A sine qua non condition is to share the materials publicly online, as far as possible. Repositories on servers such as OSF or GitHub are often sufficient to this end. Unfortunately, most studies in the cognitive sciences still do not share the complete materials.&lt;/p>
&lt;p>One of the reasons why sharing is so important is to prevent wrong assumptions by the audience that will consider the research. That is, when the materials of a study are not publicly shared online, the readers of the papers are left with two options: to assume that there were no errors or to assume that were some errors of an uncertain degree. The method followed in the creation of the materials should free the readers of this tribulation, by allowing them to consult the materials and their preparation in full, or as completely as possible.&lt;/p>
&lt;/div>
&lt;div id="reproducibility" class="section level2">
&lt;h2>Reproducibility&lt;/h2>
&lt;p>It is convenient to allow others, and our future selves, to reproduce the materials throughout their preparation and at any time thereafter. For this purpose, &lt;strong>R&lt;/strong> can be used to register in scripts as many as possible of the steps followed throughout the preparation of the materials. Far from being only a software for data analysis, R allows the preparation of texts, images, audios, etc. Humans err, by definition. That can be counted on. Conveniently, registering the steps followed during weeks or months of preparation allows us to offload part of the documentation efforts. It’s a way of video-recording, as it were, all the additions, subtractions, replacements, transformations and calculations performed with the raw materials, for the creation of the final materials.&lt;/p>
&lt;/div>
&lt;div id="generous-documentation" class="section level2">
&lt;h2>Generous documentation&lt;/h2>
&lt;p>Under the curse of knowledge, the creators of research materials may believe that their materials are self-explanatory. Often they are more obscure than they think. To allow any other stakeholders, including their future selves, to exercise the five allowances listed above—i.e., explore, understand, reproduce, modify, and reuse the materials—, the preparation process and the end materials should be documented with enough detail. This can be done using README.txt files throughout the project. Using the &lt;code>.txt&lt;/code> format/extension is recommended because other formats, such as Microsoft Word, may not be (fully) available in some computers. To exemplify the format and the content of readme files, below is an excerpt from a longitudinal study on which I’ve been working.&lt;/p>
&lt;textarea readonly style='border-color: lightgrey; overflow-x: auto; overflow-y: hidden; color: darkblue; font-size: 90%; width: 100%; max-width: 100%; height: auto; white-space: pre; overflow-wrap: normal; padding-right: 0.5em; padding-left: 1em;'>
-- Post-training test --
In Sessions 2, 3, 4 and 6, if the test is failed in the first attempt, the training and the test are
repeated (following González Alonso et al., 2020). In such cases, the result is shown at the end
of the second attempt. The session advances if the accuracy achieved in the second attempt exceeds
80%, whereas the session stops if the accuracy is lower. In the latter situation, an 'End of session'
message is presented, flanked by two orange circles, and followed by an acknowledgement for the
participant. Once the participant has read this screen, the experimenter quits the session by
pressing 'ESC' and then 'Q'.
== Stimuli ==
The stimulus lists are described in the R functions that were used to create the stimuli, as well as
in the 'list' column in the stimulus files.
== Participant-specific parameters for lab-based sessions ==
Each participant was assigned certain parameters in advance, including the mini-language, the order
of the resting-state parts, and the stimulus lists. The code that was used to create this assignment
is available in the 'stimulus_preparation' folder.
Due to the pre-assignment of the parameters, there is a fixed set of participant IDs that can be
used in OpenSesame. These identification numbers range between 1 and 144. If an ID outside of this
range is used, the OpenSesame session does not run.
== General procedure for lab-based sessions ==
At the beginning of lab-based Sessions 2, 3, 4 and 6, the experimenter will first signal the lab is
busy using a light or a sign. Next, they will ascertain what participant and what session applies.
This is done using the session logbook that is shared among all session conductors. This session
logbook is instantly updated online using a cloud service, such as OneDrive.
Next, the experimenter starts OpenSesame by opening the program directly (not by opening the
session-specific file), and then opens the appropriate session within OpenSesame. This procedure
helps prevent the opening of a standalone Python window, the closing of which would result in the
closing of OpenSesame. Next, the experimenter opens BrainVision Recorder.
When the participant arrives in the lab, they are informed that they can use the toilet outside.
The participant is also offered some water.
Next, the size of their head is measured, and an appropriate cap is tried on the participant’s
head. Next, the cap is placed on a dummy head, and the electrodes are attached to the cap. At
that point, to prevent signal interference, the participant is kindly asked to either put their
mobile devices (phone, tablet, smartwatch) in flight mode, or to leave them outside of the booth.
Next, to protect the participant's clothes from any drops of gel, a towel is placed on their
upper back, covering shoulders and upper torso. Both ends of the towel are clipped together at
the front using two or three clothes pegs. Next, the cap is fitted on the participant's head. To
prevent the cap from being pulled back during the session, the splitter box is attached to the
towel on the participant's back, right below their head. Next, measures are taken to adjust the
position of the cap evenly, first from the nasion to the inion, and then from the tip of an ear
to the other ear.
Next, the experimenter returns to OpenSesame and runs the session in full screen by clicking on
the full green triangle at the top left. Then, a file explorer window opens, in which the
experimenter must assign a subject number consistent with the session logbook, and must select
the destination folder for the logfile. The destination folder is called 'logfiles'. Any prompts
to overwrite a logfile must normally be refused, or considered carefully, due to the risk of
losing data from previous sessions.
In the first screen, the experimenter can disable some of the tasks. This option can be used if a
session has ended abruptly, in which case the session can be resumed from a near checkpoint. In
such a case, the experimenter must first note this incident in their logbook, and rename the log
file that was produced on the first run, by appending '_first_run' to the name. This prevents
overwriting the file on the second run. Next, they must open a new session, enter the same
participant ID, and select the appropriate part from which to begin. This part must be the part
immediately following the last part that was completed in full. For instance, if a session ended
abruptly during the experiment, the beginning selected on the second run would be the experiment.
Once the session has finished completely, the first log file and the second log file must be
safely merged into a single file, keeping only the fully completed tasks.
In the first instructional screen, participants are asked to refrain from asking any questions
unless it is necessary, so that all participants can receive the same instructions.
At the beginning of the resting-state part in Session 2, and at the beginning of the Experiment
part, instructions are presented on the screen that ask participants to stay as still as possible
during the following task. The screen contains an orange-coloured square with the letters 'i.s.r',
that remind the experimenter to check the impedance and the signal, and finally to begin recording
the EEG signal. If the impedance of any electrodes is poor, the experimenter may enter the booth
to lower the impedance of the electrodes affected. Otherwise, after validating the signal and the
impedance, the experimenter can begin the recording in BrainVision, and press the letter 'C' twice
in the stimulus computer. At that point, a green circle will appear, along with instructions for
the participant.
Similarly, at the end of the eyes-closed resting-state measurement (which is five minutes long),
the experimenter must intervene when they see the screen with the orange stripes, by knocking on
the door to let the participant open their eyes.
Furthermore, at the end of the resting-state part and at the end of the Experiment part, a screen
with a crossed-out R appears to remind the experimenter to stop recording the EEG.
Notice that the above-mentioned stages, characterised by screens with orange stripes, require the
experimenter's intervention. The experimenter must allow the participant to read any text on these
screens. Next, the experimenter must press the letter 'C' twice to let the session continue. This
protocol provides the experimenter with control when necessary. The experimenter should be aware
of the use of the letter 'C' at these points, as the requirement is not signalled on the screen
to prevent participants from pressing the letter themselves.
During the experiment, it is important to monitor the EEG signal. If it ever becomes very noisy,
the experimenter must wait until the next break and the participant to stop, so that the signal
can be verified. If the noise in the signal is due to the participant's movement, they should be
asked again to please stay as still possible. If the noise is due to an increase in the
impedance of some electrodes, the impedance of those electrodes should be revised.
The experiment in Session 2 contains breaks every 40 trials, whereas the experiments in subsequent
sessions contain breaks every 50 trials. During these breaks, the number of the current trial
appears in grey on the bottom right corner of the screen.
If a session ends abruptly during the experiment, but there is not enough time to restart the
session from the experiment, then the data should be uploaded to the repository.
== Definition of items in OpenSesame (only for programming purposes, not for in-session use) ==
-- Each major part of the session is contained in a sequence item that is named in capital
letters (e.g., 'PRETRAINING', 'TRAINING', 'TEST', 'EXPERIMENT').
-- 'continue_space': allows proceeding to the following screen after pressing the space bar,
which should be done by the participant. In most cases, two presses are required, as
detailed on the screen.
-- 'continue_c': allows proceeding to the following screen after pressing the letter 'C',
which should be done by the experimenter. In most cases, two presses are required, as
detailed on the screen.
== Variables in the OpenSesame log files ==
In the log files produced by OpenSesame, each part of the session (e.g., Test, Experiment) is
identified in the variable 'session_part'. The names of the response variables are 'response',
'response_time' and 'correct'. Item-specific response variables follow the formats of
'response_[item_name]', 'response_time_[item_name]' and 'correct_[item_name]'
(see https://osdoc.cogsci.nl/3.3/manual/variables/#response-variables).
The output is verbose and requires preprocessing of the data. For instance, the last response
in each loop may appear twice in the output, due to the processing of the response. These
duplicates can--and must--be cleaned up by discarding the rows that have the same trial number
as the preceding row.
== EEG triggers ==
Triggers are sent to the EEG recorder throughout the experiment. The system for sending
triggers is set up in OpenSesame script within the inline script 'EEG_trigger_setup'.
The key to the triggers is provided below.
0: reset trigger port in BrainVision Recorder. This trigger is integrated in the
trigger-sending function.
-- Resting-state EEG part --
10: beginning of eyes-open resting-state EEG
11: end of eyes-open resting-state EEG
12: beginning of eyes-closed resting-state EEG
13: end of eyes-closed resting-state EEG
-- Experiment part --
5: fixation mark
-- ID of each target sentence (only applicable to target trials) --
110--253: triggers ranging between 110 and 253, time-locked to the onset of the
word of interest in each trial.
&lt;/textarea>
&lt;script>(function(){var ta=document.currentScript.previousElementSibling;ta.style.height='auto';ta.style.height=ta.scrollHeight+'px';})();&lt;/script>
&lt;div id="comments-in-code-scripts" class="section level3">
&lt;h3>Comments in code scripts&lt;/h3>
&lt;p>It is helpful for our future selves, for our collaborators, and for any other stakeholders associated with a project—which includes any fellow researchers worldwide—to include comments in code scripts. These comments should introduce the purpose of the script at the top, and the purpose of various components of the code. Some excerpts are shown below as examples.&lt;/p>
&lt;script src='https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Ffrequentist_bayesian_plot.R%23L3-L35&amp;style=a11y-dark&amp;type=code&amp;showFullPath=on&amp;showCopy=on&amp;showLineNumbers=on&amp;showFileMeta=on'>&lt;/script>
&lt;script src='https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Fdata%2Fsemanticpriming_data_preparation.R%23L29-L60&amp;style=a11y-dark&amp;type=code&amp;showFullPath=on&amp;showCopy=on&amp;showLineNumbers=on&amp;showFileMeta=on'>&lt;/script>
&lt;/div>
&lt;/div>
&lt;div id="open-source-software" class="section level2">
&lt;h2>Open-source software&lt;/h2>
&lt;p>Where possible, open-source software should be used. Open-source software is free, and hence more accessible. Open-source software can be classified in various dimensions, such as the size of the user base. The more users, the greater the support, because the core developers have more resources, and the users will often help each other in public forums such as Stack Exchange. For instance, a programming language such as R boasts millions of users worldwide who count on support in public forums and in R-specific forums such as the &lt;a href="https://community.rstudio.com">Posit Community&lt;/a>.&lt;/p>
&lt;p>Other software are not as large. For instance, open-source software for psychological research (e.g., &lt;a href="https://osdoc.cogsci.nl/">OpenSesame&lt;/a>, &lt;a href="https://www.psychopy.org/">psychoPy&lt;/a>) are far smaller than R in terms of community. Yet, these software too can count on substantial support. For the more basic uses, most of the way has already been paved, and the existing documentation suffices. For more advanced uses, the smaller size of the community can become more obvious, as one needs to spend more time looking for solutions.&lt;/p>
&lt;p>Regardless of the size of the community, all else being equal, open-source software is the right choice to ensure access to one’s work for all (potential) stakeholders in the future. The other option, proprietary software, entails dependence on the services of a private company.&lt;/p>
&lt;/div>
&lt;div id="tidiness-and-parsimony-in-computer-code" class="section level2">
&lt;h2>Tidiness and parsimony in computer code&lt;/h2>
&lt;p>Code scripts should be as tidy and parsimonious as possible. For instance, to prevent overly long scripts that would impair the comprehension of the materials, it is useful to break down large projects into nested scripts, and &lt;code>source&lt;/code> (i.e., run) the smaller scripts in the larger scripts.&lt;/p>
&lt;pre class="r">&lt;code># Compose all stimuli for Sessions 2, 3, 4 and 6
# Create participant-specific parameters
source(&amp;#39;stimulus_preparation/participant_parameters.R&amp;#39;)
# Frame base images
source(&amp;#39;stimulus_preparation/base_images.R&amp;#39;)
# Session 2
source(&amp;#39;stimulus_preparation/Session 2/Session2_compile_all_stimuli.R&amp;#39;)
# Session 3
source(&amp;#39;stimulus_preparation/Session 3/Session3_compile_all_stimuli.R&amp;#39;)
# Session 4
source(&amp;#39;stimulus_preparation/Session 4/Session4_compile_all_stimuli.R&amp;#39;)
# Session 6
source(&amp;#39;stimulus_preparation/Session 6/Session6_compile_all_stimuli.R&amp;#39;)&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="tidiness-and-parsimony-in-project-directories" class="section level2">
&lt;h2>Tidiness and parsimony in project directories&lt;/h2>
&lt;p>A directory tree is useful to display all the folders in a project. The tree can be produced in the RStudio ‘Terminal’ console using the following one-line command.&lt;/p>
&lt;pre>&lt;code>find . -type d | sed -e &amp;quot;s/[^-][^\/]*\// |/g&amp;quot; -e &amp;quot;s/|\([^ ]\)/| - \1/&amp;quot;&lt;/code>&lt;/pre>
&lt;p>The output will look like the following (excerpt from &lt;a href="https://osf.io/gt5uf/wiki" class="uri">https://osf.io/gt5uf/wiki&lt;/a>).&lt;/p>
&lt;pre>&lt;code>.
| - bayesian_priors
| | - plots
| - semanticpriming
| | - analysis_with_visualsimilarity
| | | - model_diagnostics
| | | | - results
| | | | - plots
| | | - results
| | | - plots
| | | - correlations
| | | | - plots
| | - frequentist_bayesian_plots
| | | - plots
| | - frequentist_analysis
| | | - model_diagnostics
| | | | - results
| | | | - plots
| | | - lexical_covariates_selection
| | | | - results
| | | | - plots
| | | - results
| | | - plots&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="conclusion" class="section level2">
&lt;h2>Conclusion&lt;/h2>
&lt;p>Adhering to best practices—including the FAIR principles—in the creation of research materials enhances transparency, accessibility and reproducibility in scientific research. These standards facilitate researchers’ work beyond the short term, and increase the reliability of scientific work, thus contributing to the best use of resources.&lt;/p>
&lt;/div>
&lt;/div></description><category>research materials</category><category>experimental stimuli</category><category>research methods</category><category>programming</category><category>R</category><category>s</category><category>research methods</category><category>R</category></item><item><title>Preprocessing the Norwegian Web as Corpus (NoWaC) in R</title><link>https://pablobernabeu.github.io/2023/preprocessing-the-norwegian-web-as-corpus-nowac-in-r/</link><pubDate>Thu, 28 Sep 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/preprocessing-the-norwegian-web-as-corpus-nowac-in-r/</guid><description>
&lt;div id="the-present-script-can-be-used-to-preprocess-data-from-a-frequency-list-of-the-norwegian-as-web-corpus-nowac-guevara-2010." class="section level3">
&lt;h3>The present script can be used to preprocess data from a frequency list of the Norwegian as Web Corpus (NoWaC; Guevara, 2010).&lt;/h3>
&lt;p>Before using the script, the frequency list should be downloaded from &lt;a href="https://www.hf.uio.no/iln/english/about/organization/text-laboratory/projects/nowac/nowac-frequency.html">this URL&lt;/a>. The list is described as ‘frequency list sorted primary alphabetic and secondary by frequency within each character’, and &lt;a href="https://www.tekstlab.uio.no/nowac/download/nowac-1.1.lemma.frek.sort_alf_frek.txt.gz">this is the direct URL&lt;/a>. The download requires signing in to an institutional network. Last, the downloaded file should be unzipped.&lt;/p>
&lt;p>The script is shown below.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Fpreprocessing-NoWaC-Corpus-in-R%2Fblob%2Fmain%2Fpreprocessing_NoWaC_Corpus.R%23L19-L102&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Guevara, E. R. (2010). NoWaC: A large web-based corpus for Norwegian. In &lt;em>Proceedings of the NAACL HLT 2010 Sixth Web as Corpus Workshop&lt;/em> (pp. 1-7). &lt;a href="https://aclanthology.org/W10-1501" class="uri">https://aclanthology.org/W10-1501&lt;/a>&lt;/p>
&lt;p>Rodina, Y., &amp;amp; Westergaard, M. (2015). Grammatical gender in Norwegian: Language acquisition and language change. &lt;em>Journal of Germanic Linguistics, 27&lt;/em>(2), 145–187. &lt;a href="https://doi.org/10.1017/S1470542714000245" class="uri">https://doi.org/10.1017/S1470542714000245&lt;/a>&lt;/p>
&lt;p>Rodina, Y., &amp;amp; Westergaard, M. (2021). Grammatical gender and declension class in language change: A study of the loss of feminine gender in Norwegian. &lt;em>Journal of Germanic Linguistics, 33&lt;/em>(3), 235–263. &lt;a href="https://doi.org/10.1017/S1470542719000217" class="uri">https://doi.org/10.1017/S1470542719000217&lt;/a>&lt;/p>
&lt;/div></description><category>R</category><category>corpora</category><category>corpus</category><category>Norwegian</category><category>NoWaC</category><category>linguistics</category><category>language</category><category>research methods</category><category>s</category><category>R</category></item><item><title>ggplotting power curves from the simr package</title><link>https://pablobernabeu.github.io/2023/ggplotting-power-curves-from-simr-package/</link><pubDate>Tue, 27 Jun 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/ggplotting-power-curves-from-simr-package/</guid><description>
&lt;p>The R package ‘simr’ has greatly facilitated power analysis for mixed-effects models using Monte Carlo simulation (which involves running hundreds or thousands of tests under slight variations of the data). The &lt;code>powerCurve&lt;/code> function is used to estimate the statistical power for various sample sizes in one go. Since the tests are run serially, they can take a VERY long time; approximately, the time it takes to run the model supplied once (say, a few hours) &lt;em>times&lt;/em> the number of simulations (&lt;code>nsim&lt;/code>, which should be higher than 200), and &lt;em>times&lt;/em> the number of different sample sizes examined. While there isn’t a built-in parallel method, the power curves for different sample sizes can be run separately, and the results can be progressively combined as each component finishes running (see &lt;a href="https://pablobernabeu.github.io/2021/parallelizing-simr-powercurve">tutorial&lt;/a>). The power curves produced by &lt;code>simr&lt;/code> are so good they deserve ‘ggplot2’ rendering. So, here’s a function for it.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FpowercurvePlot%2Fblob%2Fmain%2FpowercurvePlot.R%23L3-L82&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;div id="a-usage-example" class="section level2">
&lt;h2>A usage example&lt;/h2>
&lt;pre class="r">&lt;code>library(lme4)
library(simr)
library(ggplot2)
# Toy model with data from &amp;#39;simr&amp;#39; package
fit = lmer(y ~ x + (x | g), data = simdata)
# Extend sample size of `g`
fit_extended_g = extend(fit, along = &amp;#39;g&amp;#39;, n = 12)
fit_powercurve =
powerCurve(fit_extended_g, fixed(&amp;#39;x&amp;#39;),
along = &amp;#39;g&amp;#39;, breaks = c(4, 6, 8, 10, 12),
nsim = 50, seed = 123, progress = FALSE)
# Read in custom function to ggplot results from simr::powerCurve
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/powercurvePlot/main/powercurvePlot.R&amp;#39;)
powercurvePlot(fit_powercurve, number_x_axis_levels = 6) +
# Change some defaults
xlab(&amp;quot;Number of levels in &amp;#39;g&amp;#39;&amp;quot;) +
theme(plot.title = element_blank(),
axis.title.x = element_text(size = 18),
axis.title.y = element_text(size = 18),
axis.text = element_text(size = 17))&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2023/ggplotting-power-curves-from-simr-package/index.en_files/figure-html/unnamed-chunk-1-1.png" width="672" alt="ggplot2 power curve: statistical power rising from 46% at 4 levels of 'g' to 100% at 12, with confidence intervals and an 80% reference line." />&lt;/p>
&lt;/div></description><category>power analysis</category><category>statistical power</category><category>simr</category><category>research methods</category><category>visualisation</category><category>s</category><category>R</category></item><item><title>How to discretise the colour variable in sjPlot::plot_model into equally-sized intervals</title><link>https://pablobernabeu.github.io/2023/how-to-discretise-colour-variable-in-sjplot-plot-model-into-equally-sized-intervals/</link><pubDate>Sat, 24 Jun 2023 16:54:46 +0200</pubDate><guid>https://pablobernabeu.github.io/2023/how-to-discretise-colour-variable-in-sjplot-plot-model-into-equally-sized-intervals/</guid><description>
&lt;p>Whereas the direction of main effects can be interpreted from the sign of the estimate, the interpretation of interaction effects often requires plots. This task is facilitated by the R package &lt;a href="https://strengejacke.github.io/sjPlot">&lt;code>sjPlot&lt;/code>&lt;/a>. For instance, using the &lt;code>plot_model&lt;/code> function, I plotted the interaction between two continuous variables.&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
#&amp;gt; Loading required package: Matrix
library(sjPlot)
#&amp;gt; Learn more about sjPlot with &amp;#39;browseVignettes(&amp;quot;sjPlot&amp;quot;)&amp;#39;.
library(ggplot2)
theme_set(theme_sjplot())
# Create data partially based on code by Ben Bolker
# from https://stackoverflow.com/a/38296264/7050882
set.seed(101)
spin = runif(800, 1, 24)
trait = rep(1:40, each = 20)
ID = rep(1:80, each = 10)
testdata &amp;lt;- data.frame(spin, trait, ID)
testdata$fatigue &amp;lt;-
testdata$spin * testdata$trait /
rnorm(800, mean = 6, sd = 2)
# Model
fit = lmer(fatigue ~ spin * trait + (1|ID),
data = testdata, REML = TRUE)
#&amp;gt; boundary (singular) fit: see help(&amp;#39;isSingular&amp;#39;)
plot_model(fit, type = &amp;#39;pred&amp;#39;, terms = c(&amp;#39;spin&amp;#39;, &amp;#39;trait&amp;#39;))
#&amp;gt; Warning: Ignoring unknown parameters: linewidth&lt;/code>&lt;/pre>
&lt;p>&lt;img src="7VTcfLu.png" alt="sjPlot line chart of predicted fatigue versus spin with default trait colour bins at 8.9, 20.5 and 32.1" />&lt;!-- -->&lt;/p>
&lt;p>&lt;sup>Created on 2023-06-24 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p>
&lt;p>However, I needed an extra feature, as sjPlot by default breaks down the colour (&lt;code>fill&lt;/code>) variable into few levels that do not include the minimum or the maximum values in my variable. What I would like to do is to stratify the colour variable into equally-sized levels that include the minimum and the maximum values.&lt;/p>
&lt;p>Furthermore, in the legend, I would also like to display the number of levels of a grouping variable (&lt;code>ID&lt;/code>) that are contained in each level of the colour variable.&lt;/p>
&lt;p>Below is a solution using &lt;a href="https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-ten-or-six-bins">custom functions called &lt;code>deciles_interaction_plot&lt;/code> and &lt;code>sextiles_interaction_plot&lt;/code>&lt;/a>.&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
#&amp;gt; Loading required package: Matrix
library(sjPlot)
library(ggplot2)
theme_set(theme_sjplot())
# Create data partially based on code by Ben Bolker
# from https://stackoverflow.com/a/38296264/7050882
set.seed(101)
spin = runif(800, 1, 24)
trait = rep(1:40, each = 20)
ID = rep(1:80, each = 10)
testdata &amp;lt;- data.frame(spin, trait, ID)
testdata$fatigue &amp;lt;-
testdata$spin * testdata$trait /
rnorm(800, mean = 6, sd = 2)
# Model
fit = lmer(fatigue ~ spin * trait + (1|ID),
data = testdata, REML = TRUE)
#&amp;gt; boundary (singular) fit: see help(&amp;#39;isSingular&amp;#39;)
# plot_model(fit, type = &amp;#39;pred&amp;#39;, terms = c(&amp;#39;spin&amp;#39;, &amp;#39;trait&amp;#39;))
# Binning the colour variable into ten levels (deciles)
# Read in function from GitHub
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/main/R_functions/deciles_interaction_plot.R&amp;#39;)
deciles_interaction_plot(
model = fit,
x = &amp;#39;spin&amp;#39;,
fill = &amp;#39;trait&amp;#39;,
fill_nesting_factor = &amp;#39;ID&amp;#39;
)
#&amp;gt; Loading required package: dplyr
#&amp;gt;
#&amp;gt; Attaching package: &amp;#39;dplyr&amp;#39;
#&amp;gt; The following objects are masked from &amp;#39;package:stats&amp;#39;:
#&amp;gt;
#&amp;gt; filter, lag
#&amp;gt; The following objects are masked from &amp;#39;package:base&amp;#39;:
#&amp;gt;
#&amp;gt; intersect, setdiff, setequal, union
#&amp;gt; Loading required package: RColorBrewer
#&amp;gt; Loading required package: ggtext
#&amp;gt; Loading required package: Cairo
#&amp;gt; Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette Set1 is 9
#&amp;gt; Returning the palette you asked for with that many colors
#&amp;gt; Warning: Ignoring unknown parameters: linewidth
#&amp;gt; Scale for &amp;#39;y&amp;#39; is already present. Adding another scale for &amp;#39;y&amp;#39;, which will
#&amp;gt; replace the existing scale.
#&amp;gt; Scale for &amp;#39;colour&amp;#39; is already present. Adding another scale for &amp;#39;colour&amp;#39;,
#&amp;gt; which will replace the existing scale.&lt;/code>&lt;/pre>
&lt;p>&lt;img src="niqWOzx.png" alt="Predicted fatigue versus spin with trait split into ten equal deciles (1.00 to 40.00), legend showing n=8 IDs per bin" />&lt;!-- -->&lt;/p>
&lt;pre class="r">&lt;code>
# If you wanted or needed to make six levels (sextiles) instead
# of ten, you could use the function sextiles_interaction_plot.
# Read in function from GitHub
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/main/R_functions/sextiles_interaction_plot.R&amp;#39;)
sextiles_interaction_plot(
model = fit,
x = &amp;#39;spin&amp;#39;,
fill = &amp;#39;trait&amp;#39;,
fill_nesting_factor = &amp;#39;ID&amp;#39;
)
#&amp;gt; Warning: Ignoring unknown parameters: linewidth
#&amp;gt; Scale for &amp;#39;y&amp;#39; is already present. Adding another scale for &amp;#39;y&amp;#39;, which will
#&amp;gt; replace the existing scale.
#&amp;gt; Scale for &amp;#39;colour&amp;#39; is already present. Adding another scale for &amp;#39;colour&amp;#39;,
#&amp;gt; which will replace the existing scale.&lt;/code>&lt;/pre>
&lt;p>&lt;img src="w8Ydo4F.png" alt="Predicted fatigue versus spin with trait split into six equal sextiles (1.00 to 40.00), legend showing ID counts per bin" />&lt;!-- -->&lt;/p>
&lt;p>&lt;sup>Created on 2023-06-24 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p></description><category>visualisation</category><category>linear-mixed effects models</category><category>interactions</category><category>binning</category><category>sjPlot</category><category>Individual differences</category><category>s</category><category>R</category><category>statistics</category></item><item><title>How to map more informative values onto fill argument of sjPlot::plot_model</title><link>https://pablobernabeu.github.io/2023/how-to-map-more-informative-values-onto-fill-argument-of-sjplot-plot-model/</link><pubDate>Sat, 24 Jun 2023 16:51:11 +0200</pubDate><guid>https://pablobernabeu.github.io/2023/how-to-map-more-informative-values-onto-fill-argument-of-sjplot-plot-model/</guid><description>
&lt;p>Whereas the direction of main effects can be interpreted from the sign of the estimate, the interpretation of interaction effects often requires plots. This task is facilitated by the R package &lt;a href="https://strengejacke.github.io/sjPlot">&lt;code>sjPlot&lt;/code>&lt;/a>. For instance, using the &lt;code>plot_model&lt;/code> function, I plotted the interaction between a continuous variable and a categorical variable. The categorical variable was passed to the &lt;code>fill&lt;/code> argument of plot_model.&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
#&amp;gt; Loading required package: Matrix
library(sjPlot)
#&amp;gt; Install package &amp;quot;strengejacke&amp;quot; from GitHub (`devtools::install_github(&amp;quot;strengejacke/strengejacke&amp;quot;)`) to load all sj-packages at once!
library(ggplot2)
theme_set(theme_sjplot())
cake$recipe_recoded = ifelse(cake$recipe == &amp;#39;A&amp;#39;, -0.5,
ifelse(cake$recipe == &amp;#39;B&amp;#39;, 0,
ifelse(cake$recipe == &amp;#39;C&amp;#39;, 0.5,
NA)))
fit = lmer(angle ~ recipe_recoded * temp +
(1|recipe_recoded:replicate),
cake, REML= FALSE)
plot_model(fit, type = &amp;#39;pred&amp;#39;, terms = c(&amp;#39;temp&amp;#39;, &amp;#39;recipe_recoded&amp;#39;))
#&amp;gt; Warning: Ignoring unknown parameters: linewidth&lt;/code>&lt;/pre>
&lt;p>&lt;img src="SiigAMp.png" alt="sjPlot interaction plot of predicted angle vs temperature, legend 'recipe_recoded' showing sum-coded values -0.5, 0, 0.5" />&lt;!-- -->&lt;/p>
&lt;p>&lt;sup>Created on 2023-06-24 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p>
&lt;p>However, I needed an extra feature, as the categorical variable was not quite informative because it was a sum-coded transformation. Thus, I wanted the legend of the plot to show the values of the original variable (i.e., A, B and C), instead of those of the sum-coded variable that had been used in the model (i.e., -0.5, 0 and 0.5).&lt;/p>
&lt;p>Below is a solution using a custom function called &lt;a href="https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-alias-variables">&lt;code>alias_interaction_plot&lt;/code>&lt;/a>.&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
#&amp;gt; Loading required package: Matrix
library(sjPlot)
library(ggplot2)
theme_set(theme_sjplot())
cake$recipe_recoded = ifelse(cake$recipe == &amp;#39;A&amp;#39;, -0.5,
ifelse(cake$recipe == &amp;#39;B&amp;#39;, 0,
ifelse(cake$recipe == &amp;#39;C&amp;#39;, 0.5,
NA)))
fit = lmer(angle ~ recipe_recoded * temp +
(1|recipe_recoded:replicate),
cake, REML= FALSE)
# plot_model(fit, type = &amp;#39;pred&amp;#39;, terms = c(&amp;#39;temp&amp;#39;, &amp;#39;recipe_recoded&amp;#39;))
# Displaying the original variable instead
# Read in function from GitHub
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/main/R_functions/alias_interaction_plot.R&amp;#39;)
alias_interaction_plot(
model = fit,
dataset = cake,
x = &amp;#39;temp&amp;#39;,
fill = &amp;#39;recipe_recoded&amp;#39;,
fill_alias = &amp;#39;recipe&amp;#39;,
fill_title = &amp;#39;recipe&amp;#39;
)
#&amp;gt; Loading required package: rlang
#&amp;gt; Loading required package: dplyr
#&amp;gt;
#&amp;gt; Attaching package: &amp;#39;dplyr&amp;#39;
#&amp;gt; The following objects are masked from &amp;#39;package:stats&amp;#39;:
#&amp;gt;
#&amp;gt; filter, lag
#&amp;gt; The following objects are masked from &amp;#39;package:base&amp;#39;:
#&amp;gt;
#&amp;gt; intersect, setdiff, setequal, union
#&amp;gt; Loading required package: RColorBrewer
#&amp;gt; Loading required package: ggtext
#&amp;gt; Loading required package: Cairo
#&amp;gt; Warning: Ignoring unknown parameters: linewidth
#&amp;gt; Scale for &amp;#39;y&amp;#39; is already present. Adding another scale for &amp;#39;y&amp;#39;, which will
#&amp;gt; replace the existing scale.
#&amp;gt; Scale for &amp;#39;colour&amp;#39; is already present. Adding another scale for &amp;#39;colour&amp;#39;,
#&amp;gt; which will replace the existing scale.&lt;/code>&lt;/pre>
&lt;p>&lt;img src="SS03gK6.png" alt="Same interaction plot with custom function, legend 'recipe' showing original values A, B, C instead of sum-coded ones" />&lt;!-- -->&lt;/p>
&lt;p>&lt;sup>Created on 2023-06-24 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p></description><category>linear-mixed effects models</category><category>interactions</category><category>sjPlot</category><category>alias</category><category>recode</category><category>visualisation</category><category>s</category><category>R</category><category>statistics</category></item><item><title>How to visually assess the convergence of a mixed-effects model by plotting various optimizers</title><link>https://pablobernabeu.github.io/2023/how-to-visually-assess-the-convergence-of-a-mixed-effects-model-by-plotting-various-optimizers/</link><pubDate>Sat, 24 Jun 2023 16:42:34 +0200</pubDate><guid>https://pablobernabeu.github.io/2023/how-to-visually-assess-the-convergence-of-a-mixed-effects-model-by-plotting-various-optimizers/</guid><description>
&lt;p>To assess whether convergence warnings render the results invalid, or on the contrary, the results can be deemed valid in spite of the warnings, &lt;a href="https://cran.r-project.org/web/packages/lme4/lme4.pdf">Bates et al. (2023)&lt;/a> suggest refitting models affected by convergence warnings with a variety of optimizers. The authors argue that, if the different optimizers produce practically-equivalent results, the results are valid. The &lt;code>allFit&lt;/code> function from the ‘lme4’ package allows the refitting of models using a number of optimizers. To use the seven optimizers listed above, two extra packages must be installed: ‘dfoptim’ and ‘optimx’ (see lme4 manual). The output from &lt;code>allFit&lt;/code> contains several statistics on the fixed and the random effects fitted by each optimizer.&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
#&amp;gt; Loading required package: Matrix
library(dfoptim)
library(optimx)
# Create data using code by Ben Bolker from
# https://stackoverflow.com/a/38296264/7050882
set.seed(101)
spin = runif(600, 1, 24)
reg = runif(600, 1, 15)
ID = rep(c(&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;, &amp;quot;6&amp;quot;, &amp;quot;7&amp;quot;, &amp;quot;8&amp;quot;, &amp;quot;9&amp;quot;, &amp;quot;10&amp;quot;))
day = rep(1:30, each = 10)
testdata &amp;lt;- data.frame(spin, reg, ID, day)
testdata$fatigue &amp;lt;- testdata$spin * testdata$reg/10 * rnorm(30, mean=3, sd=2)
# Model
fit = lmer(fatigue ~ spin * reg + (1|ID),
data = testdata, REML = TRUE)
# Refit model using all available algorithms
multi_fit = allFit(fit)
#&amp;gt; bobyqa : [OK]
#&amp;gt; Nelder_Mead : [OK]
#&amp;gt; nlminbwrap : [OK]
#&amp;gt; nmkbw : [OK]
#&amp;gt; optimx.L-BFGS-B : [OK]
#&amp;gt; nloptwrap.NLOPT_LN_NELDERMEAD : [OK]
#&amp;gt; nloptwrap.NLOPT_LN_BOBYQA : [OK]
# Show results
summary(multi_fit)$fixef
#&amp;gt; (Intercept) spin reg spin:reg
#&amp;gt; bobyqa -2.975678 0.5926561 0.1437204 0.1834016
#&amp;gt; Nelder_Mead -2.975675 0.5926559 0.1437202 0.1834016
#&amp;gt; nlminbwrap -2.975677 0.5926560 0.1437203 0.1834016
#&amp;gt; nmkbw -2.975678 0.5926561 0.1437204 0.1834016
#&amp;gt; optimx.L-BFGS-B -2.975680 0.5926562 0.1437205 0.1834016
#&amp;gt; nloptwrap.NLOPT_LN_NELDERMEAD -2.975666 0.5926552 0.1437196 0.1834017
#&amp;gt; nloptwrap.NLOPT_LN_BOBYQA -2.975678 0.5926561 0.1437204 0.1834016
# Read in function from GitHub
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/plot.fixef.allFit/main/plot.fixef.allFit.R&amp;#39;)
plot.fixef.allFit(multi_fit,
select_predictors = c(&amp;#39;spin&amp;#39;, &amp;#39;reg&amp;#39;, &amp;#39;spin:reg&amp;#39;),
# Increase padding at top and bottom of Y axis
multiply_y_axis_limits = 1.3,
y_title = &amp;#39;Fixed effect (*b*)&amp;#39;)
#&amp;gt; Loading required package: dplyr
#&amp;gt;
#&amp;gt; Attaching package: &amp;#39;dplyr&amp;#39;
#&amp;gt; The following objects are masked from &amp;#39;package:stats&amp;#39;:
#&amp;gt;
#&amp;gt; filter, lag
#&amp;gt; The following objects are masked from &amp;#39;package:base&amp;#39;:
#&amp;gt;
#&amp;gt; intersect, setdiff, setequal, union
#&amp;gt; Loading required package: reshape2
#&amp;gt; Loading required package: stringr
#&amp;gt; Loading required package: scales
#&amp;gt; Loading required package: ggplot2
#&amp;gt; Loading required package: ggtext
#&amp;gt; Loading required package: patchwork&lt;/code>&lt;/pre>
&lt;p>&lt;img src="XYQDug2.png" alt="Panels of fixed effects across 7 optimizers, all converging to nearly identical values on a shared Y axis" />&lt;!-- -->&lt;/p>
&lt;pre class="r">&lt;code>
# Alternative using plot-specific Y axes and other modified settings
plot.fixef.allFit(multi_fit,
select_predictors = c(&amp;#39;spin&amp;#39;, &amp;#39;spin:reg&amp;#39;),
# Use plot-specific Y axis limits
shared_y_axis_limits = FALSE,
decimal_places = 7,
# Move up Y axis title
y_title_hjust = 4.5,
y_title = &amp;#39;Fixed effect (*b*)&amp;#39;)&lt;/code>&lt;/pre>
&lt;p>&lt;img src="BYXJYxM.png" alt="Fixed effects across 7 optimizers on plot-specific Y axes zoomed to 7 decimals, showing tiny differences between optimizers" />&lt;!-- -->&lt;/p>
&lt;p>&lt;sup>Created on 2023-06-26 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p></description><category>convergence</category><category>research methods</category><category>statistics</category><category>linear-mixed effects models</category><category>visualisation</category><category>s</category><category>R</category><category>statistics</category></item><item><title>Table joins with conditional "fuzzy" string matching in R</title><link>https://pablobernabeu.github.io/2023/table-joins-with-conditional-fuzzy-string-matching-in-r/</link><pubDate>Sat, 24 Jun 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/table-joins-with-conditional-fuzzy-string-matching-in-r/</guid><description>
&lt;p>Here’s an example of fuzzy-matching strings in R that I shared on &lt;a href="https://stackoverflow.com/a/76368552/7050882">StackOverflow&lt;/a>. In &lt;code>stringdist_join&lt;/code>, the &lt;code>max_dist&lt;/code> argument is used to constrain the degree of fuzziness.&lt;/p>
&lt;pre class="r">&lt;code>library(fuzzyjoin)
library(dplyr)
#&amp;gt;
#&amp;gt; Attaching package: &amp;#39;dplyr&amp;#39;
#&amp;gt; The following objects are masked from &amp;#39;package:stats&amp;#39;:
#&amp;gt;
#&amp;gt; filter, lag
#&amp;gt; The following objects are masked from &amp;#39;package:base&amp;#39;:
#&amp;gt;
#&amp;gt; intersect, setdiff, setequal, union
library(knitr)
small_tab = data.frame(Food.Name = c(&amp;#39;Corn&amp;#39;, &amp;#39;Squash&amp;#39;, &amp;#39;Peppers&amp;#39;),
Food.Code = c(NA, NA, NA))
large_tab = data.frame(Food.Name = c(&amp;#39;Sweet Corn&amp;#39;, &amp;#39;Red Corn&amp;#39;, &amp;#39;Baby Corns&amp;#39;,
&amp;#39;Squash&amp;#39;, &amp;#39;Long Squash&amp;#39;, &amp;#39;Red Pepper&amp;#39;,
&amp;#39;Green Pepper&amp;#39;, &amp;#39;Red Peppers&amp;#39;),
Food.Code = c(532, 532, 944, 111, 123, 654, 655, 654))
joined_tab = stringdist_join(small_tab, large_tab, by = &amp;#39;Food.Name&amp;#39;,
ignore_case = TRUE, method = &amp;#39;cosine&amp;#39;,
max_dist = 0.5, distance_col = &amp;#39;dist&amp;#39;) %&amp;gt;%
# Tidy columns
select(Food.Name = Food.Name.x, -Food.Name.y,
Food.Code = Food.Code.y, -dist) %&amp;gt;%
# Only keep most frequent food code per food name
group_by(Food.Name) %&amp;gt;% count(Food.Name, Food.Code) %&amp;gt;%
slice(which.max(n)) %&amp;gt;% select(-n) %&amp;gt;%
# Order food names as in the small table
arrange(factor(Food.Name, levels = small_tab$Food.Name))
# Show table with columns renamed
joined_tab %&amp;gt;%
rename(&amp;#39;Food Name&amp;#39; = Food.Name,
&amp;#39;Food Code&amp;#39; = Food.Code) %&amp;gt;%
kable()&lt;/code>&lt;/pre>
&lt;table>
&lt;thead>
&lt;tr class="header">
&lt;th align="left">Food Name&lt;/th>
&lt;th align="right">Food Code&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="left">Corn&lt;/td>
&lt;td align="right">532&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Squash&lt;/td>
&lt;td align="right">111&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Peppers&lt;/td>
&lt;td align="right">654&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;sup>Created on 2023-05-31 with &lt;a href="https://reprex.tidyverse.org">reprex v2.0.2&lt;/a>&lt;/sup>&lt;/p></description><category>string matching</category><category>s</category><category>R</category></item><item><title>A new function to plot convergence diagnostics from lme4::allFit()</title><link>https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/</link><pubDate>Thu, 22 Jun 2023 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/index_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/index_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/index_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;p>Linear mixed-effects models (LMM) offer a consistent way of performing regression and analysis of variance tests which allows accounting for non-independence in the data. Over the past decades, LMMs have subsumed most of the General Linear Model, with a steady increase in popularity (Meteyard &amp;amp; Davies, 2020). Since their conception, LMMs have presented the challenge of model &lt;em>convergence&lt;/em>. In essence, the issue of convergence boils down to the widespread tension between parsimony and completeness in data analysis. That is, on the one hand, a good model must allow an accurate, parsimonious analysis of each predictor, and thus, it must not be overfitted with too many parameters. Yet, on the other hand, the model must be complete enough to account for a sufficient amount of variation in the data. In LMMs, any predictors that entail non-independent observations (also known as repeated measures) will normally bring both fixed and random effects into the model. Where a few of these predictors coexist, models often struggle to find enough information in the data to account for every predictor—and especially, for every random effect. This difficulty translates into convergence warnings (Brauer &amp;amp; Curtin, 2018; Singmann &amp;amp; Kellen, 2019). In this article, I review the issue of convergence before presenting a new plotting function in R that facilitates the diagnosis of convergence by visualising the fixed effects fitted by different optimization algorithms (also dubbed optimizers).&lt;/p>
&lt;div id="completeness-versus-parsimony" class="section level2">
&lt;h2>Completeness versus parsimony&lt;/h2>
&lt;p>Both fixed and random effects comprise intercepts and slopes. The pressure exerted by each of those types of effects on the model is determined by the number of data points involved by each. First, slopes are more demanding than intercepts, as they involve a (far) larger number of data points. Second, random effects are more demanding than fixed effects, as random effects entail the number of estimates required for fixed effects &lt;em>times&lt;/em> the number of levels in the grouping factor. As a result, on the most lenient end of the scale lies the fixed intercept, and on the heaviest end lie the random slopes. Convergence warnings in LMMs are often due to the random slopes alone.&lt;/p>
&lt;p>Sounds easy, then! Not inviting the random slopes to the party should solve the problem. Indeed, since random slopes involve the highest number of estimates by far, removing them does often remove convergence warnings. This, however, leads to a different problem. Surrendering the information provided by random slopes can result in the violation of the assumption of independence of observations. For years, the removal of random slopes due to convergence warnings was standard practice. Currently, in contrast, proposals increasingly consider other options, such as removing random effects if they do not significantly improve the fit of the model (Matuschek et al., 2017), and keeping the random slopes in the model in spite of the convergence warnings to safeguard the assumption of independence (see Table 17 in Brauer &amp;amp; Curtin, 2018; Singmann &amp;amp; Kellen, 2019).&lt;/p>
&lt;/div>
&lt;div id="the-multiple-optimizers-sanity-check-from-lme4allfit" class="section level2">
&lt;h2>The multiple-optimizers sanity check from &lt;code>lme4::allFit()&lt;/code>&lt;/h2>
&lt;p>Framed within the drive to maintain random slopes wherever possible, the developers of the ‘lme4’ package propose a sanity check that uses a part of the ‘lme4’ &lt;em>engine&lt;/em> called ‘optimizer’. Every model has a default optimizer, unless a specific one is chosen through &lt;code>control = lmerControl(optimizer = '...')&lt;/code> (in lmer models) or &lt;code>control = glmerControl(optimizer = '...')&lt;/code> (in glmer models). The seven widely-available optimizers are:&lt;/p>
&lt;ul>
&lt;li>bobyqa&lt;/li>
&lt;li>Nelder_Mead&lt;/li>
&lt;li>nlminbwrap&lt;/li>
&lt;li>nmkbw&lt;/li>
&lt;li>optimx.L-BFGS-B&lt;/li>
&lt;li>nloptwrap.NLOPT_LN_NELDERMEAD&lt;/li>
&lt;li>nloptwrap.NLOPT_LN_BOBYQA&lt;/li>
&lt;/ul>
&lt;p>To assess whether convergence warnings render the results invalid, or on the contrary, the results can be deemed valid in spite of the warnings, Bates et al. (2022) suggest refitting models affected by convergence warnings with a variety of optimizers. The authors argue that if the different optimizers produce practically-equivalent results, the results are valid. The &lt;code>allFit&lt;/code> function from the ‘lme4’ package allows the refitting of models using a number of optimizers. To use the seven optimizers listed above, two extra packages must be installed: ‘dfoptim’ and ‘optimx’ (see &lt;a href="https://cran.r-project.org/web/packages/lme4/lme4.pdf">lme4 manual&lt;/a>). The output from &lt;code>allFit()&lt;/code> contains several statistics on the fixed and the random effects fitted by each optimizer (see &lt;a href="https://github.com/lme4/lme4/issues/512#issue-425198940">example&lt;/a>).&lt;/p>
&lt;/div>
&lt;div id="plotting-the-fixed-effects-from-allfit" class="section level2">
&lt;h2>Plotting the fixed effects from allFit()&lt;/h2>
&lt;p>Several R users have ventured into &lt;a href="https://www.google.com/search?q=%22ggplot%22+%22allfit%22+optimizers">plotting the allFit() output&lt;/a> but there is not a function in ‘lme4’ yet at the time of writing. Bernabeu (2022) developed a &lt;a href="https://github.com/pablobernabeu/plot.fixef.allFit/blob/main/plot.fixef.allFit.R">function&lt;/a> that takes the output from &lt;code>allFit()&lt;/code>, tidies it, selects the fixed effects and plots them using ‘ggplot2’. The function is shown below, and can be copied through the &lt;code>Copy Code&lt;/code> button at the top right corner. It can be renamed by changing &lt;code>plot.fixef.allFit&lt;/code> to another valid name.&lt;/p>
&lt;div style="height: 800px; border: 0.5px dotted grey; padding: 10px; resize: both; overflow: auto;">
&lt;pre class="r">&lt;code># Plot the results from the fixed effects produced by different optimizers. This function
# takes the output from lme4::allFit(), tidies it, selects fixed effects and plots them.
plot.fixef.allFit = function(allFit_output,
# Set the same Y axis limits in every plot
shared_y_axis_limits = TRUE,
# Multiply Y axis limits by a factor (only
# available if shared_y_axis_limits = TRUE)
multiply_y_axis_limits = 1,
# Number of decimal places
decimal_places = NULL,
# Select predictors
select_predictors = NULL,
# Number of rows
nrow = NULL,
# Y axis title
y_title = &amp;#39;Fixed effect&amp;#39;,
# Alignment of the Y axis title
y_title_hjust = NULL,
# Add number to the names of optimizers
number_optimizers = TRUE,
# Replace colon in interactions with x
interaction_symbol_x = TRUE) {
require(lme4)
require(dfoptim)
require(optimx)
require(dplyr)
require(reshape2)
require(stringr)
require(scales)
require(ggplot2)
require(ggtext)
require(patchwork)
library(Cairo)
# Tidy allFit output
# Extract fixed effects from the allFit() output
allFit_fixef = summary(allFit_output)$fixef %&amp;gt;% # Select fixed effects in the allFit results
reshape2::melt() %&amp;gt;% # Structure the output as a data frame
rename(&amp;#39;Optimizer&amp;#39; = &amp;#39;Var1&amp;#39;, &amp;#39;fixed_effect&amp;#39; = &amp;#39;Var2&amp;#39;) # set informative names
# If number_optimizers = TRUE, assign number to each optimizer and place it before its name
if(number_optimizers == TRUE) {
allFit_fixef$Optimizer = paste0(as.numeric(allFit_fixef$Optimizer), &amp;#39;. &amp;#39;, allFit_fixef$Optimizer)
}
# If select_predictors was supplied, select them along with the intercept (the latter required)
if(!is.null(select_predictors)) {
allFit_fixef = allFit_fixef %&amp;gt;% dplyr::filter(fixed_effect %in% c(&amp;#39;(Intercept)&amp;#39;, select_predictors))
}
# Order variables
allFit_fixef = allFit_fixef[, c(&amp;#39;Optimizer&amp;#39;, &amp;#39;fixed_effect&amp;#39;, &amp;#39;value&amp;#39;)]
# PLOT. The overall plot is formed of a first row containing the intercept and the legend
# (intercept_plot), and a second row containing the predictors (predictors_plot),
# which may in turn occupy several rows.
# If multiply_y_axis_limits was supplied but shared_y_axis_limits = FALSE,
# warn that shared_y_axis_limits is required.
if(!multiply_y_axis_limits == 1 &amp;amp; shared_y_axis_limits == FALSE) {
message(&amp;#39;The argument `multiply_y_axis_limits` has not been used because \n it requires `shared_y_axis_limits` set to TRUE.&amp;#39;)
}
# If extreme values were entered in y_title_hjust, show warning
if(!is.null(y_title_hjust)) {
if(y_title_hjust &amp;lt; 0.5 | y_title_hjust &amp;gt; 6) {
message(&amp;#39;NOTE: For y_title_hjust, a working range of values is between 0.6 and 6.&amp;#39;)
}
}
# If decimal_places was supplied, convert number to the format used in &amp;#39;scales&amp;#39; package
if(!is.null(decimal_places)) {
decimal_places =
ifelse(decimal_places == 1, 0.1,
ifelse(decimal_places == 2, 0.01,
ifelse(decimal_places == 3, 0.001,
ifelse(decimal_places == 4, 0.0001,
ifelse(decimal_places == 5, 0.00001,
ifelse(decimal_places == 6, 0.000001,
ifelse(decimal_places == 7, 0.0000001,
ifelse(decimal_places == 8, 0.00000001,
ifelse(decimal_places == 9, 0.000000001,
ifelse(decimal_places == 10, 0.0000000001,
ifelse(decimal_places == 11, 0.00000000001,
ifelse(decimal_places == 12, 0.000000000001,
ifelse(decimal_places == 13, 0.0000000000001,
ifelse(decimal_places == 14, 0.00000000000001,
ifelse(decimal_places &amp;gt;= 15, 0.000000000000001,
0.001
)))))))))))))))
}
# First row: intercept_plot
# Select intercept data only
intercept = allFit_fixef %&amp;gt;% dplyr::filter(fixed_effect == &amp;#39;(Intercept)&amp;#39;)
intercept_plot = intercept %&amp;gt;%
ggplot(., aes(fixed_effect, value, colour = Optimizer)) +
geom_point(position = position_dodge(1)) +
facet_wrap(~fixed_effect, scale = &amp;#39;free&amp;#39;) +
guides(colour = guide_legend(title.position = &amp;#39;left&amp;#39;)) +
theme_bw() +
theme(axis.title = element_blank(), axis.ticks.x = element_blank(),
axis.text.x = element_blank(),
strip.text = element_text(size = 10, margin = margin(t = 4, b = 6)),
strip.background = element_rect(fill = &amp;#39;grey96&amp;#39;),
legend.margin = margin(0.3, 0, 0.8, 1, &amp;#39;cm&amp;#39;),
legend.title = element_text(size = unit(15, &amp;#39;pt&amp;#39;), angle = 90, hjust = 0.5))
# Second row: predictors_plot
# Select all predictors except intercept
predictors = allFit_fixef %&amp;gt;% dplyr::filter(!fixed_effect == &amp;#39;(Intercept)&amp;#39;)
# If interaction_symbol_x = TRUE (default), replace colon with times symbol x between spaces
if(interaction_symbol_x == TRUE) {
# Replace colon in interactions with \u00D7, i.e., x; then set factor class
predictors$fixed_effect = predictors$fixed_effect %&amp;gt;%
str_replace_all(&amp;#39;:&amp;#39;, &amp;#39; \u00D7 &amp;#39;) %&amp;gt;% factor()
}
# Order predictors as in the original output from lme4::allFit()
predictors$fixed_effect = factor(predictors$fixed_effect,
levels = unique(predictors$fixed_effect))
# Set number of rows for the predictors excluding the intercept.
# First, if nrow argument supplied, use it
if(!is.null(nrow)) {
predictors_plot_nrow = nrow - 1 # Subtract 1 as intercept row not considered
# Else, if nrow argument not supplied, calculate sensible number of rows: i.e., divide number of
# predictors (exc. intercept) by 2 and round up the result. For instance, 7 predictors --&amp;gt; 3 rows
} else predictors_plot_nrow = (length(unique(predictors$fixed_effect)) / 2) %&amp;gt;% ceiling()
predictors_plot = ggplot(predictors, aes(fixed_effect, value, colour = Optimizer)) +
geom_point(position = position_dodge(1)) +
facet_wrap(~fixed_effect, scale = &amp;#39;free&amp;#39;,
# Note that predictors_plot_nrow was defined a few lines above
nrow = predictors_plot_nrow,
# Wrap names of predictors with more than 54 characters into new lines
labeller = labeller(fixed_effect = label_wrap_gen(width = 55))) +
labs(y = y_title) +
theme_bw() +
theme(axis.title.x = element_blank(), axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
axis.title.y = ggtext::element_markdown(size = 14, margin = margin(0, 15, 0, 0)),
strip.text = element_text(size = 10, margin = margin(t = 4, b = 6)),
strip.background = element_rect(fill = &amp;#39;grey96&amp;#39;), legend.position = &amp;#39;none&amp;#39;)
# Below, the function scale_y_continuous is applied conditionally to avoid overriding settings. First,
# if shared_y_axis_limits = TRUE and decimal_places was supplied, set the same Y axis limits in
# every plot and set decimal_places. By default, also expand limits by a seventh of its original
# limit, and allow further multiplication of limits through multiply_y_axis_limits.
if(shared_y_axis_limits == TRUE &amp;amp; !is.null(decimal_places)) {
intercept_plot = intercept_plot +
scale_y_continuous(limits = c(min(allFit_fixef$value) - allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits,
max(allFit_fixef$value) + allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits),
# Set number of decimal places
labels = scales::label_number(accuracy = decimal_places))
predictors_plot = predictors_plot +
scale_y_continuous(limits = c(min(allFit_fixef$value) - allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits,
max(allFit_fixef$value) + allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits),
# Set number of decimal places
labels = scales::label_number(accuracy = decimal_places))
# Else, if shared_y_axis_limits = TRUE but decimal_places were not supplied, do as above but without
# setting decimal_places.
} else if(shared_y_axis_limits == TRUE &amp;amp; is.null(decimal_places)) {
intercept_plot = intercept_plot +
scale_y_continuous(limits = c(min(allFit_fixef$value) - allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits,
max(allFit_fixef$value) + allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits),
# Set number of decimal places
labels = scales::label_number(accuracy = decimal_places))
predictors_plot = predictors_plot +
scale_y_continuous(limits = c(min(allFit_fixef$value) - allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits,
max(allFit_fixef$value) + allFit_fixef$value %&amp;gt;% abs %&amp;gt;%
max / 7 * multiply_y_axis_limits),
# Set number of decimal places
labels = scales::label_number(accuracy = decimal_places))
# Else, if shared_y_axis_limits = FALSE and decimal_places was supplied, set decimal_places.
} else if(shared_y_axis_limits == FALSE &amp;amp; !is.null(decimal_places)) {
# Set number of decimal places in both plots
intercept_plot = intercept_plot +
scale_y_continuous(labels = scales::label_number(accuracy = decimal_places))
predictors_plot = predictors_plot +
scale_y_continuous(labels = scales::label_number(accuracy = decimal_places))
}
# Plot matrix: based on number of predictors_plot_nrow, adjust height of Y axis title
# (unless supplied), and assign space to intercept_plot and predictors_plot
if(predictors_plot_nrow == 1) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 3.6))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 11, l = 0) # predictors row(s)
)
} else if(predictors_plot_nrow == 2) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 1.4))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 16, l = 0) # predictors row(s)
)
} else if(predictors_plot_nrow == 3) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 0.92))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 21, l = 0) # predictors row(s)
)
} else if(predictors_plot_nrow == 4) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 0.8))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 26, l = 0) # predictors row(s)
)
} else if(predictors_plot_nrow == 5) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 0.73))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 31, l = 0) # predictors row(s)
)
} else if(predictors_plot_nrow &amp;gt; 5) {
# If y_title_hjust supplied, use it
if(!is.null(y_title_hjust)) {
predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = y_title_hjust))
# Otherwise, set a sensible height
} else predictors_plot = predictors_plot +
theme(axis.title.y = ggtext::element_markdown(hjust = 0.65))
layout = c(
patchwork::area(t = 1.5, r = 8.9, b = 6.8, l = 0), # intercept row
patchwork::area(t = 7.3, r = 9, b = 36, l = 0) # predictors row(s)
)
# Also, advise user to consider distributing predictors into several plots
message(&amp;#39; Many rows! Consider distributing predictors into several plots \n using argument `select_predictors`&amp;#39;)
}
# Add margin
predictors_plot = predictors_plot + theme(plot.margin = margin(15, 15, 15, 15))
# Return matrix of plots
wrap_plots(intercept_plot, predictors_plot, design = layout,
# The 2 below corresponds to intercept_plot and predictors_plot
nrow = 2)
}&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="optional-arguments" class="section level3">
&lt;h3>Optional arguments&lt;/h3>
&lt;p>Below are the optional arguments allowed by the function, with their default values.&lt;/p>
&lt;pre>&lt;code># Set the same Y axis limits in every plot
shared_y_axis_limits = TRUE,
# Multiply Y axis limits by a factor (only
# available if shared_y_axis_limits = TRUE)
multiply_y_axis_limits = 1,
# Number of decimal places
decimal_places = NULL,
# Select predictors
select_predictors = NULL,
# Number of rows
nrow = NULL,
# Y axis title
y_title = &amp;#39;Fixed effect&amp;#39;,
# Alignment of the Y axis title
y_title_hjust = NULL,
# Add number to the names of optimizers
number_optimizers = TRUE,
# Replace colon in interactions with x
interaction_symbol_x = TRUE
&lt;/code>&lt;/pre>
&lt;p>The argument &lt;code>shared_y_axis_limits&lt;/code> deserves a comment. It allows using the same Y axis limits (i.e., range) in all plots or, alternatively, using plot-specific limits. The parameter is &lt;code>TRUE&lt;/code> by default to prevent overinterpretations of small differences across optimizers (see the first figure below). In contrast, when &lt;code>shared_y_axis_limits = FALSE&lt;/code>, plot-specific limits are used, which results in a narrower range of values in the Y axis (see the second figure below). Since data points will span the entire Y axis in that case, any difference across optimizers—regardless of its relative importance—might be perceived as large, unless the specific range of values in each plot is noticed.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="use-case" class="section level2">
&lt;h2>Use case&lt;/h2>
&lt;p>Let’s test the function with a minimal model.&lt;/p>
&lt;pre class="r">&lt;code># Create data using code by Ben Bolker from
# https://stackoverflow.com/a/38296264/7050882
set.seed(101)
spin = runif(600, 1, 24)
reg = runif(600, 1, 15)
ID = rep(c(&amp;quot;1&amp;quot;,&amp;quot;2&amp;quot;,&amp;quot;3&amp;quot;,&amp;quot;4&amp;quot;,&amp;quot;5&amp;quot;, &amp;quot;6&amp;quot;, &amp;quot;7&amp;quot;, &amp;quot;8&amp;quot;, &amp;quot;9&amp;quot;, &amp;quot;10&amp;quot;))
day = rep(1:30, each = 10)
testdata &amp;lt;- data.frame(spin, reg, ID, day)
testdata$fatigue &amp;lt;- testdata$spin * testdata$reg/10 * rnorm(30, mean=3, sd=2)
# Model
library(lme4)
fit = lmer(fatigue ~ spin * reg + (1|ID),
data = testdata, REML = TRUE)
# Refit model using all available algorithms
multi_fit = allFit(fit)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## bobyqa : [OK]
## Nelder_Mead : [OK]
## nlminbwrap : [OK]
## nmkbw : [OK]
## optimx.L-BFGS-B : [OK]
## nloptwrap.NLOPT_LN_NELDERMEAD : [OK]
## nloptwrap.NLOPT_LN_BOBYQA : [OK]&lt;/code>&lt;/pre>
&lt;pre class="r">&lt;code>summary(multi_fit)$fixef&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## (Intercept) spin reg spin:reg
## bobyqa -2.975678 0.5926561 0.1437204 0.1834016
## Nelder_Mead -2.975675 0.5926559 0.1437202 0.1834016
## nlminbwrap -2.975677 0.5926560 0.1437203 0.1834016
## nmkbw -2.975678 0.5926561 0.1437204 0.1834016
## optimx.L-BFGS-B -2.975680 0.5926562 0.1437205 0.1834016
## nloptwrap.NLOPT_LN_NELDERMEAD -2.975666 0.5926552 0.1437196 0.1834017
## nloptwrap.NLOPT_LN_BOBYQA -2.975678 0.5926561 0.1437204 0.1834016&lt;/code>&lt;/pre>
&lt;p>The effects to be visualised are selected below using the argument &lt;code>select_predictors&lt;/code>. Notice that the intercept is plotted by default on the first row, along with the legend that lists all the optimizers used.&lt;/p>
&lt;pre class="r">&lt;code># Read in function from GitHub
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/plot.fixef.allFit/main/plot.fixef.allFit.R&amp;#39;)
plot.fixef.allFit(multi_fit,
select_predictors = c(&amp;#39;spin&amp;#39;, &amp;#39;reg&amp;#39;, &amp;#39;spin:reg&amp;#39;),
# Increase padding at top and bottom of Y axis
multiply_y_axis_limits = 1.3,
y_title = &amp;#39;Fixed effect (*b*)&amp;#39;,
# Align y title
y_title_hjust = .9)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## Warning: package &amp;#39;dplyr&amp;#39; was built under R version 4.5.2&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## Warning: package &amp;#39;ggplot2&amp;#39; was built under R version 4.5.2&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/index_files/figure-html/demo-plot.fixef.allFit-function-1-1.png" width="864" style="display: block; margin: auto;" alt="Faceted dot plot of fixed effects (intercept, spin, reg, spin x reg) on a shared y axis; the 7 optimizers' estimates overlap, showing convergence." />&lt;/p>
&lt;p>The plot produced by &lt;code>plot.fixef.allFit()&lt;/code> by default replaces the colons in interaction effects (e.g., &lt;code>spin:reg&lt;/code>) with ’ × ’ to facilitate the visibility (this can be overriden by setting &lt;code>interaction_symbol_x = FALSE&lt;/code>). Yet, it is important to note that any interactions passed to &lt;code>select_predictors&lt;/code> must have the colon, as that is the symbol present in the &lt;code>lme4::allFit()&lt;/code> output.&lt;/p>
&lt;p>The output of &lt;code>plot.fixef.allFit()&lt;/code> is a &lt;a href="https://ggplot2.tidyverse.org/">ggplot2&lt;/a> object that can be stored for further use, as in the example below, in which new parameters are used.&lt;/p>
&lt;pre class="r">&lt;code>library(ggplot2)
plot_fit_convergence =
plot.fixef.allFit(multi_fit,
select_predictors = c(&amp;#39;spin&amp;#39;, &amp;#39;spin:reg&amp;#39;),
# Use plot-specific Y axis limits
shared_y_axis_limits = FALSE,
decimal_places = 7,
# Move up Y axis title
y_title_hjust = -20,
y_title = &amp;#39;Fixed effect (*b*)&amp;#39;)
# Print
plot_fit_convergence&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2023/a-new-function-to-plot-convergence-diagnostics-from-lme4-allfit/index_files/figure-html/demo-plot.fixef.allFit-function-2-1.png" width="864" style="display: block; margin: auto;" alt="Faceted dot plot of intercept, spin and spin x reg effects with plot-specific y axes and 7 decimals, revealing tiny differences among the 7 optimizers." />&lt;/p>
&lt;pre class="r">&lt;code># Plot can be saved to disk as pdf, png, etc. through `ggplot2::ggsave()`
# ggsave(&amp;#39;plot_fit_convergence.pdf&amp;#39;, plot_fit_convergence,
# device = cairo_pdf, width = 9, height = 9, dpi = 900)&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bates, D., Maechler, M., Bolker, B., Walker, S., Christensen, R. H. B., Singmann, H., Dai, B., Scheipl, F., Grothendieck, G., Green, P., Fox, J., Bauer, A., &amp;amp; Krivitsky, P. N. (2022). &lt;em>Package ‘lme4’.&lt;/em> CRAN. &lt;a href="https://cran.r-project.org/web/packages/lme4/lme4.pdf" class="uri">https://cran.r-project.org/web/packages/lme4/lme4.pdf&lt;/a>&lt;/p>
&lt;p>Bernabeu, P. (2022). Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Brauer, M., &amp;amp; Curtin, J. J. (2018). Linear mixed-effects models and the analysis of nonindependent data: A unified framework to analyze categorical and continuous independent variables that vary within-subjects and/or within-items. &lt;em>Psychological Methods, 23&lt;/em>(3), 389–411. &lt;a href="https://doi.org/10.1037/met0000159" class="uri">https://doi.org/10.1037/met0000159&lt;/a>&lt;/p>
&lt;p>Matuschek, H., Kliegl, R., Vasishth, S., Baayen, H., &amp;amp; Bates, D. (2017). Balancing type 1 error and power in linear mixed models. &lt;em>Journal of Memory and Language, 94&lt;/em>, 305–315. &lt;a href="https://doi.org/10.1016/j.jml.2017.01.001" class="uri">https://doi.org/10.1016/j.jml.2017.01.001&lt;/a>&lt;/p>
&lt;p>Meteyard, L., &amp;amp; Davies, R. A. (2020). Best practice guidance for linear mixed-effects models in psychological science. &lt;em>Journal of Memory and Language, 112&lt;/em>, 104092. &lt;a href="https://doi.org/10.1016/j.jml.2020.104092" class="uri">https://doi.org/10.1016/j.jml.2020.104092&lt;/a>&lt;/p>
&lt;p>Singmann, H., &amp;amp; Kellen, D. (2019). An introduction to mixed models for experimental psychology. In D. H. Spieler &amp;amp; E. Schumacher (Eds.), &lt;em>New methods in cognitive psychology&lt;/em> (pp. 4–31). Psychology Press.&lt;/p>
&lt;/div></description><category>s</category><category>R</category><category>linear mixed-effects models</category><category>visualisation</category><category>statistics</category><category>R</category><category>linear mixed-effects models</category></item><item><title>A table of results for Bayesian mixed-effects models: Grouping variables and specifying random slopes</title><link>https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/</link><pubDate>Thu, 29 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/kePrint/kePrint.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/lightable/lightable.css" rel="stylesheet" />
&lt;p>Here I share the format applied to tables presenting the results of &lt;em>Bayesian&lt;/em> models in Bernabeu (2022; the &lt;a href="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes">table for frequentist models is covered in this other post&lt;/a>). The sample table presents a Bayesian mixed-effects model that was fitted using the R package &lt;a href="https://cran.r-project.org/web/packages/brms/brms.pdf">&lt;code>brms&lt;/code>&lt;/a> (Bürkner et al., 2022). The mixed effects were driven by the maximal principle (Brauer &amp;amp; Curtin, 2018). The format of the table resembles one of the examples published by the &lt;a href="https://apastyle.apa.org/style-grammar-guidelines/tables-figures/sample-tables">American Psychological Association&lt;/a>. However, there are also deviations from those examples. For instance, in the present table, the effects are grouped under informative labels to facilitate the readers’ comprehension, using the &lt;a href="https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf">&lt;code>kableExtra&lt;/code>&lt;/a> package (Zhu, 2022). Furthermore, the random slopes are specified using superscript letters and a footnote. The table can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>.&lt;/p>
&lt;div id="loading-packages-and-the-results-of-the-models" class="section level3">
&lt;h3>Loading packages and the results of the models&lt;/h3>
&lt;pre class="r">&lt;code>library(dplyr)
library(knitr)
library(tibble)
library(stringr)
library(lmerTest)
library(kableExtra)
# Load Bayesian results summary
semanticpriming_summary_weaklyinformativepriors_exgaussian =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/bayesian_analysis/results/semanticpriming_summary_weaklyinformativepriors_exgaussian.rds?raw=true&amp;#39;)))&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="adjusting-the-names-of-the-effects" class="section level3">
&lt;h3>Adjusting the names of the effects&lt;/h3>
&lt;p>First, to facilitate the understanding of the results, the original names of the effects will be adjusted in the &lt;code>brms&lt;/code> summary.&lt;/p>
&lt;pre class="r">&lt;code># Rename effects in plain language and specify the random slopes
# (if any) for each effect, in the footnote. For this purpose,
# superscripts are added to the names of the appropriate effects.
#
# In the interactions below, word-level variables are presented
# first for the sake of consistency (the order does not affect
# the results in any way). Also in the interactions, double
# colons are used to inform the &amp;#39;bayesian_model_table&amp;#39;
# function that the two terms in the interaction must be split
# into two lines.
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_attentional_control&amp;#39;] = &amp;#39;Attentional control&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_attentional_control&amp;#39;] = &amp;#39;Attentional control&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_vocabulary_size&amp;#39;] = &amp;#39;Vocabulary size &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_recoded_participant_gender&amp;#39;] = &amp;#39;Gender &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_target_word_frequency&amp;#39;] = &amp;#39;Word frequency&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_target_number_syllables&amp;#39;] = &amp;#39;Number of syllables&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_word_concreteness_diff&amp;#39;] = &amp;#39;Word-concreteness difference&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_cosine_similarity&amp;#39;] = &amp;#39;Language-based similarity &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_visual_rating_diff&amp;#39;] = &amp;#39;Visual-strength difference &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_recoded_interstimulus_interval&amp;#39;] = &amp;#39;Stimulus onset asynchrony (SOA) &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_word_concreteness_diff:z_vocabulary_size&amp;#39;] =
&amp;#39;Word-concreteness difference :: Vocabulary size&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_word_concreteness_diff:z_recoded_interstimulus_interval&amp;#39;] =
&amp;#39;Word-concreteness difference : SOA&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_word_concreteness_diff:z_recoded_participant_gender&amp;#39;] =
&amp;#39;Word-concreteness difference : Gender&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_attentional_control:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Attentional control&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_attentional_control:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Attentional control&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_vocabulary_size:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Vocabulary size&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_vocabulary_size:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Vocabulary size&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_recoded_participant_gender:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity : Gender&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_recoded_participant_gender:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference : Gender&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_cosine_similarity:z_recoded_interstimulus_interval&amp;#39;] =
&amp;#39;Language-based similarity : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed)[
rownames(semanticpriming_summary_weaklyinformativepriors_exgaussian$fixed) ==
&amp;#39;z_visual_rating_diff:z_recoded_interstimulus_interval&amp;#39;] =
&amp;#39;Visual-strength difference : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="bayesian_model_table" class="section level3">
&lt;h3>&lt;code>bayesian_model_table()&lt;/code>&lt;/h3>
&lt;p>In Bernabeu (2022), the following custom function was used.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Fbayesian_model_table.R%23L3-L181&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>The above function was used to render a PDF output. In the current scenario, however, we have an HTML output. In the above function, the code used for the &lt;span class="math inline">\(\widehat{R}\)&lt;/span> tailored to the HTML output (&lt;code>&amp;amp;Rcirc;&lt;/code>) does not render properly.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Fbayesian_model_table.R%23L119-L121&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;p>Instead, the LaTeX code &lt;code>$\\widehat{R}$&lt;/code> must be used. Therefore, we’ll correct this error and load the function below.&lt;/p>
&lt;pre class="r">&lt;code># Function used in the manuscript to present summaries from &amp;#39;brms&amp;#39; models
# in APA-formatted tables. The only obligatory argument to be supplied is
# a summary of a &amp;#39;brms&amp;#39; model.
bayesian_model_table =
function(model_summary, show_intercept = TRUE, select_effects = NULL,
order_effects = NULL, format = NULL,
# If interaction_symbol_x = TRUE, replace double colons with
# times symbols followed by line breaks and indentation.
# Then, replace single colons with times symbols.
interaction_symbol_x = FALSE,
caption = &amp;#39;Summary of the lmerTest model.&amp;#39;) {
require(dplyr)
require(knitr)
require(tibble)
require(stringr)
require(lmerTest)
require(kableExtra)
# Create data frame
model_summary =
data.frame(Effect = rownames(model_summary$fixed),
Estimate = model_summary$fixed$Estimate,
SE = model_summary$fixed$Est.Error,
CrI_2.5 = model_summary$fixed$`l-95% CI`,
CrI_97.5 = model_summary$fixed$`u-95% CI`,
Rhat = model_summary$fixed$Rhat,
row.names = NULL)
# Process credible intervals and present both inside square brackets
model_summary$CrI_2.5 = model_summary$CrI_2.5 %&amp;gt;%
# Round off and keep trailing zeros
sprintf(&amp;#39;%.2f&amp;#39;, .) %&amp;gt;%
# Remove minus sign from pure zeros
sub(&amp;#39;-0.00&amp;#39;, &amp;#39;0.00&amp;#39;, .)
model_summary$CrI_97.5 = model_summary$CrI_97.5 %&amp;gt;%
# Round off and keep trailing zeros
sprintf(&amp;#39;%.2f&amp;#39;, .) %&amp;gt;%
# Remove minus sign from pure zeros
sub(&amp;#39;-0.00&amp;#39;, &amp;#39;0.00&amp;#39;, .)
model_summary$CrI_95 = paste0(&amp;#39;[&amp;#39;, model_summary$CrI_2.5, &amp;#39;, &amp;#39;,
model_summary$CrI_97.5, &amp;#39;]&amp;#39;)
# If show_intercept = FALSE, remove it
if(isFALSE(show_intercept)) {
model_summary = model_summary %&amp;gt;% filter(!grepl(&amp;#39;Intercept&amp;#39;, Effect))
# Put &amp;#39;Intercept&amp;#39; in parentheses
} else if(!is.null(model_summary[model_summary$Effect == &amp;#39;Intercept&amp;#39;, &amp;#39;Effect&amp;#39;])) {
model_summary[model_summary$Effect == &amp;#39;Intercept&amp;#39;, &amp;#39;Effect&amp;#39;] = &amp;#39;(Intercept)&amp;#39;
}
# If select_effects was supplied, apply it and order effects accordingly
if(!is.null(select_effects)) {
model_summary = model_summary %&amp;gt;% filter(Effect %in% select_effects) %&amp;gt;%
arrange(factor(Effect, levels = select_effects))
}
# If order_effects was supplied, apply order
if(!is.null(order_effects)) {
model_summary = model_summary %&amp;gt;%
arrange(factor(Effect, levels = order_effects))
}
# Round other values
model_summary$Estimate = model_summary$Estimate %&amp;gt;% as.numeric %&amp;gt;%
# Round off and keep trailing zeros
sprintf(&amp;#39;%.2f&amp;#39;, .) %&amp;gt;%
# Remove minus sign from pure zeros
sub(&amp;#39;-0.00&amp;#39;, &amp;#39;0.00&amp;#39;, .)
model_summary$SE = model_summary$SE %&amp;gt;% as.numeric %&amp;gt;%
# Round off and keep trailing zeros
sprintf(&amp;#39;%.2f&amp;#39;, .)
model_summary$Rhat = model_summary$Rhat %&amp;gt;% as.numeric %&amp;gt;%
# Round off and keep trailing zeros
sprintf(&amp;#39;%.2f&amp;#39;, .)
# Order columns
model_summary = model_summary %&amp;gt;% select(Effect, Estimate, SE, CrI_95, Rhat)
# Right-align all columns after first one
align = c(&amp;#39;l&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;r&amp;#39;)
# Establish latex or HTML format: if no format supplied,
# try to obtain it from knitr, or apply HTML
if(missing(format) || is.null(format)) {
if(knitr::is_latex_output()) {
format = &amp;#39;latex&amp;#39;
} else format = &amp;#39;html&amp;#39;
}
# HTML format
if(format == &amp;#39;html&amp;#39;) {
# If interaction_symbol_x = TRUE, replace double colons with times
# symbols followed by line breaks and indentation. Then, replace
# single colons with times symbols.
if(interaction_symbol_x) {
model_summary$Effect = model_summary$Effect %&amp;gt;%
gsub(&amp;#39;::&amp;#39;, &amp;#39; &amp;amp;times; &amp;lt;br&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;#39;, .) %&amp;gt;%
gsub(&amp;#39;:&amp;#39;, &amp;#39; &amp;amp;times; &amp;#39;, .)
}
# Output table
model_summary %&amp;gt;%
# Remove header of first column and rename other headers
rename(&amp;#39; &amp;#39; = &amp;#39;Effect&amp;#39;, &amp;#39;&amp;amp;beta;&amp;#39; = &amp;#39;Estimate&amp;#39;, &amp;#39;&amp;lt;i&amp;gt;SE&amp;lt;/i&amp;gt;&amp;#39; = &amp;#39;SE&amp;#39;,
&amp;#39;95% CrI&amp;#39; = &amp;#39;CrI_95&amp;#39;, &amp;#39;$\\widehat{R}$&amp;#39; = &amp;#39;Rhat&amp;#39;) %&amp;gt;%
# Present table
kbl(digits = 2, booktabs = TRUE, escape = FALSE, align = align,
# Caption of the table (default unless specified)
caption = caption,
# Disable occasional line gap (https://stackoverflow.com/a/49018919/7050882)
linesep = &amp;#39;&amp;#39;) %&amp;gt;%
# Apply nice kableExtra format
kable_styling() %&amp;gt;%
# Center-align header row
row_spec(0, align = &amp;#39;c&amp;#39;)
# LaTeX format
} else {
# If interaction_symbol_x = TRUE, replace double colons with times
# symbols followed by line breaks and indentation. Then, replace
# single colons with times symbols.
if(interaction_symbol_x) {
model_summary$Effect = model_summary$Effect %&amp;gt;%
gsub(&amp;#39;::&amp;#39;, &amp;#39; $\\\\times$ \n \\\\hspace{0.3cm}&amp;#39;, .) %&amp;gt;%
gsub(&amp;#39;:&amp;#39;, &amp;#39; $\\\\times$ &amp;#39;, .)
}
model_summary$Effect = model_summary$Effect %&amp;gt;%
# Escape underscores to avoid error in table
str_replace_all(&amp;#39;_&amp;#39;, &amp;#39;\\\\_&amp;#39;) %&amp;gt;%
# Allow line breaks in the names of the effects
# (used in the interactions)
kableExtra::linebreak(align = &amp;#39;l&amp;#39;)
# Output table
model_summary %&amp;gt;%
# Remove header of first column and rename other headers
rename(&amp;#39; &amp;#39; = &amp;#39;Effect&amp;#39;, &amp;#39;$\\upbeta$&amp;#39; = &amp;#39;Estimate&amp;#39;, &amp;#39;$SE$&amp;#39; = &amp;#39;SE&amp;#39;,
&amp;#39;95\\% CrI&amp;#39; = &amp;#39;CrI_95&amp;#39;, &amp;#39;$\\widehat R$&amp;#39; = &amp;#39;Rhat&amp;#39;) %&amp;gt;%
# Present table
kbl(digits = 2, booktabs = TRUE, escape = FALSE, align = align,
# Caption of the table (default unless specified)
caption = caption,
# Disable occasional line gap (https://stackoverflow.com/a/49018919/7050882)
linesep = &amp;#39;&amp;#39;) %&amp;gt;%
# Apply nice kableExtra format
kable_styling() %&amp;gt;%
# Center-align header row
row_spec(0, align = &amp;#39;c&amp;#39;)
}
}&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="the-function-in-use" class="section level3">
&lt;h3>The function in use&lt;/h3>
&lt;pre class="r">&lt;code># Create table (using custom function from the &amp;#39;R_functions&amp;#39; folder)
bayesian_model_table(
semanticpriming_summary_weaklyinformativepriors_exgaussian,
order_effects = c(&amp;#39;(Intercept)&amp;#39;,
&amp;#39;Attentional control&amp;#39;,
&amp;#39;Vocabulary size &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Gender &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Word frequency&amp;#39;,
&amp;#39;Number of syllables&amp;#39;,
&amp;#39;Word-concreteness difference&amp;#39;,
&amp;#39;Language-based similarity &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Visual-strength difference &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Stimulus onset asynchrony (SOA) &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Word-concreteness difference :: Vocabulary size&amp;#39;,
&amp;#39;Word-concreteness difference : SOA&amp;#39;,
&amp;#39;Word-concreteness difference : Gender&amp;#39;,
&amp;#39;Language-based similarity :: Attentional control&amp;#39;,
&amp;#39;Visual-strength difference :: Attentional control&amp;#39;,
&amp;#39;Language-based similarity :: Vocabulary size&amp;#39;,
&amp;#39;Visual-strength difference :: Vocabulary size&amp;#39;,
&amp;#39;Language-based similarity : Gender&amp;#39;,
&amp;#39;Visual-strength difference : Gender&amp;#39;,
&amp;#39;Language-based similarity : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Visual-strength difference : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;),
# Replace colons in the names of interactions with times symbols
interaction_symbol_x = TRUE,
# No title
caption = NULL) %&amp;gt;%
# Group predictors under headings
pack_rows(&amp;#39;Individual differences&amp;#39;, 2, 4) %&amp;gt;%
pack_rows(&amp;#39;Target-word lexical covariates&amp;#39;, 5, 6) %&amp;gt;%
pack_rows(&amp;#39;Prime--target relationship&amp;#39;, 7, 9) %&amp;gt;%
pack_rows(&amp;#39;Task condition&amp;#39;, 10, 10) %&amp;gt;%
pack_rows(&amp;#39;Interactions&amp;#39;, 11, 21) %&amp;gt;%
# Apply white background to override default shading in HTML output
row_spec(1:21, background = &amp;#39;white&amp;#39;) %&amp;gt;%
# Highlight covariates
row_spec(c(2, 5:7, 11:15), background = &amp;#39;#FFFFF1&amp;#39;) %&amp;gt;%
# Format
kable_classic(full_width = FALSE, html_font = &amp;#39;Cambria&amp;#39;) %&amp;gt;%
# Footnote describing abbreviations, random slopes, etc.
# LaTeX code used to format the text.
footnote(escape = FALSE, threeparttable = TRUE, general_title = &amp;#39;&amp;lt;br&amp;gt;&amp;#39;,
general = paste(&amp;#39;*Note*. &amp;amp;beta; = Estimate based on $z$-scored predictors; *SE* = standard error;&amp;#39;,
&amp;#39;CrI = credible interval. Yellow rows contain covariates. Some interactions are &amp;#39;,
&amp;#39;split over two lines, with the second line indented. &amp;lt;br&amp;gt;&amp;#39;,
&amp;#39;&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; By-word random slopes were included for this effect.&amp;#39;,
&amp;#39;&amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt; By-participant random slopes were included for this effect.&amp;#39;))&lt;/code>&lt;/pre>
&lt;table class="table lightable-classic" style="margin-left: auto; margin-right: auto; font-family: Cambria; width: auto !important; margin-left: auto; margin-right: auto;border-bottom: 0;">
&lt;thead>
&lt;tr>
&lt;th style="text-align:left;text-align: center;">
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
β
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
&lt;i>SE&lt;/i>
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
95% CrI
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
&lt;span class="math inline">\(\widehat{R}\)&lt;/span>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left;background-color: white !important;">
(Intercept)
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr grouplength="3">
&lt;td colspan="5" style="border-bottom: 1px solid;">
&lt;strong>Individual differences&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Vocabulary size &lt;sup>a&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Gender &lt;sup>a&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr grouplength="2">
&lt;td colspan="5" style="border-bottom: 1px solid;">
&lt;strong>Target-word lexical covariates&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word frequency
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-0.11
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[-0.12, -0.11]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Number of syllables
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.07
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.06, 0.07]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr grouplength="3">
&lt;td colspan="5" style="border-bottom: 1px solid;">
&lt;strong>Prime–target relationship&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.06
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.07, -0.06]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.01, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr grouplength="1">
&lt;td colspan="5" style="border-bottom: 1px solid;">
&lt;strong>Task condition&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Stimulus onset asynchrony (SOA) &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.03
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.02, 0.04]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr grouplength="11">
&lt;td colspan="5" style="border-bottom: 1px solid;">
&lt;strong>Interactions&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × SOA
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Language-based similarity × &lt;br>    Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Visual-strength difference × &lt;br>    Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × SOA &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × SOA &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.00
&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;tfoot>
&lt;tr>
&lt;td style="padding: 0; " colspan="100%">
&lt;span style="font-style: italic;">&lt;br>&lt;/span>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="padding: 0; " colspan="100%">
&lt;sup>&lt;/sup> &lt;em>Note&lt;/em>. β = Estimate based on &lt;span class="math inline">\(z\)&lt;/span>-scored predictors; &lt;em>SE&lt;/em> = standard error; CrI = credible interval. Yellow rows contain covariates. Some interactions are split over two lines, with the second line indented. &lt;br> &lt;sup>a&lt;/sup> By-word random slopes were included for this effect. &lt;sup>b&lt;/sup> By-participant random slopes were included for this effect.
&lt;/td>
&lt;/tr>
&lt;/tfoot>
&lt;/table>
&lt;div id="shading-specific-rows" class="section level4">
&lt;h4>Shading specific rows&lt;/h4>
&lt;p>Shading specific rows is done differently when the output is PDF, as shown below (see p. 170 in &lt;a href="https://eprints.lancs.ac.uk/id/eprint/177833/6/2022deJuanBernabeuPhD.pdf">Bernabeu, 2022&lt;/a>).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fthesis%2Fappendix-E-Bayesian-analysis-results.Rmd%23L164-L165&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;/div>
&lt;div id="session-info" class="section level3">
&lt;h3>Session info&lt;/h3>
&lt;p>If you encounter any blockers while reproducing the table using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>, my current session info may be useful.&lt;/p>
&lt;pre class="r">&lt;code>sessionInfo()&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## R version 4.3.2 (2023-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 11 x64 (build 22621)
##
## Matrix products: default
##
##
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8
## [2] LC_CTYPE=English_United Kingdom.utf8
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United Kingdom.utf8
##
## time zone: Europe/Oslo
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] kableExtra_1.3.4 lmerTest_3.1-3 lme4_1.1-35.1
## [4] Matrix_1.6-4 stringr_1.5.1 tibble_3.2.1
## [7] dplyr_1.1.4 knitr_1.45 xaringanExtra_0.7.0
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.8 utf8_1.2.4 generics_0.1.3
## [4] xml2_1.3.6 blogdown_1.18 stringi_1.8.3
## [7] lattice_0.22-5 digest_0.6.33 magrittr_2.0.3
## [10] evaluate_0.23 grid_4.3.2 bookdown_0.37
## [13] fastmap_1.1.1 jsonlite_1.8.8 httr_1.4.7
## [16] rvest_1.0.3 fansi_1.0.6 viridisLite_0.4.2
## [19] scales_1.3.0 numDeriv_2016.8-1.1 jquerylib_0.1.4
## [22] cli_3.6.2 rlang_1.1.2 munsell_0.5.0
## [25] splines_4.3.2 withr_2.5.2 cachem_1.0.8
## [28] yaml_2.3.8 tools_4.3.2 uuid_1.1-1
## [31] nloptr_2.0.3 minqa_1.2.6 colorspace_2.1-0
## [34] ggplot2_3.4.4 webshot_0.5.5 boot_1.3-28.1
## [37] vctrs_0.6.5 R6_2.5.1 lifecycle_1.0.4
## [40] MASS_7.3-60 pkgconfig_2.0.3 pillar_1.9.0
## [43] bslib_0.6.1 gtable_0.3.4 glue_1.6.2
## [46] Rcpp_1.0.11 systemfonts_1.0.5 xfun_0.41
## [49] tidyselect_1.2.0 rstudioapi_0.15.0 htmltools_0.5.7
## [52] nlme_3.1-164 svglite_2.1.3 rmarkdown_2.25
## [55] compiler_4.3.2&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em>. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Brauer, M., &amp;amp; Curtin, J. J. (2018). Linear mixed-effects models and the analysis of nonindependent data: A unified framework to analyze categorical and continuous independent variables that vary within-subjects and/or within-items. &lt;em>Psychological Methods, 23&lt;/em>(3), 389–411. &lt;a href="https://doi.org/10.1037/met0000159" class="uri">https://doi.org/10.1037/met0000159&lt;/a>&lt;/p>
&lt;p>Bürkner, P.-C., Gabry, J., Weber, S., Johnson, A., Modrak, M., Badr, H. S., Weber, F., Ben-Shachar, M. S., &amp;amp; Rabel, H. (2022). &lt;em>Package ’brms’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/brms/brms.pdf" class="uri">https://cran.r-project.org/web/packages/brms/brms.pdf&lt;/a>&lt;/p>
&lt;p>Zhu, H. (2022). &lt;em>Package ’kableExtra’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf" class="uri">https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf&lt;/a>&lt;/p>
&lt;/div></description><category>R</category><category>statistics</category><category>rstats</category><category>brms</category><category>credible intervals</category><category>s</category><category>R</category><category>statistics</category></item><item><title>A table of results for frequentist mixed-effects models: Grouping variables and specifying random slopes</title><link>https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/</link><pubDate>Thu, 29 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;script src="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/kePrint/kePrint.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/a-table-of-results-for-frequentist-mixed-effects-models-grouping-variables-and-specifying-random-slopes/index.en_files/lightable/lightable.css" rel="stylesheet" />
&lt;p>Here I share the format applied to tables presenting the results of &lt;em>frequentist&lt;/em> models in Bernabeu (2022; the &lt;a href="https://pablobernabeu.github.io/2022/a-table-of-results-for-bayesian-mixed-effects-models-grouping-variables-and-specifying-random-slopes">table for Bayesian models is covered in this other post&lt;/a>). The sample table presents a mixed-effects model that was fitted using the R package &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">&lt;code>lmerTest&lt;/code>&lt;/a> (Kuznetsova et al., 2022). The mixed effects were driven by the maximal principle (Brauer &amp;amp; Curtin, 2018). The format of the table resembles one of the examples published by the &lt;a href="https://apastyle.apa.org/style-grammar-guidelines/tables-figures/sample-tables">American Psychological Association&lt;/a>. However, there are also deviations from those examples. For instance, in the present table, the effects are grouped under informative labels to facilitate the readers’ comprehension, using the &lt;a href="https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf">&lt;code>kableExtra&lt;/code>&lt;/a> package (Zhu, 2022). Furthermore, the random slopes are specified using superscript letters and a footnote. The table can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>.&lt;/p>
&lt;div id="loading-packages-and-the-results-of-the-models" class="section level3">
&lt;h3>Loading packages and the results of the models&lt;/h3>
&lt;pre class="r">&lt;code>library(dplyr)
library(knitr)
library(tibble)
library(stringr)
library(lmerTest)
library(kableExtra)
# Load frequentist coefficients (estimates and confidence intervals)
KR_summary_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/KR_summary_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))
confint_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/confint_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="adjusting-the-names-of-the-effects" class="section level3">
&lt;h3>Adjusting the names of the effects&lt;/h3>
&lt;p>First, to facilitate the understanding of the results, the original names of the effects will be adjusted in the &lt;code>lmerTest&lt;/code> summary and in the confidence intervals object.&lt;/p>
&lt;p>Incidentally, the confidence intervals were obtained using the &lt;code>confint.merMod&lt;/code> function from the &lt;code>lme4&lt;/code> package, as neither &lt;code>lmerTest&lt;/code> nor &lt;code>lme4&lt;/code> currently provide confidence intervals in their default results output. However, computing the confidence intervals is uncomplicated (&lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/semanticpriming_lmerTest.R#L126-L130">see code&lt;/a>).&lt;/p>
&lt;pre class="r">&lt;code># Rename effects in plain language and specify the random slopes
# (if any) for each effect, in the footnote. For this purpose,
# superscripts are added to the names of the appropriate effects.
#
# In the interactions below, word-level variables are presented
# first for the sake of consistency (the order does not affect
# the results in any way). Also in the interactions, double
# colons are used to inform the &amp;#39;frequentist_model_table&amp;#39;
# function that the two terms in the interaction must be split
# into two lines.
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_attentional_control&amp;#39;] = &amp;#39;Attentional control&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_vocabulary_size&amp;#39;] = &amp;#39;Vocabulary size &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_participant_gender&amp;#39;] = &amp;#39;Gender &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_target_word_frequency&amp;#39;] = &amp;#39;Word frequency&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_target_number_syllables&amp;#39;] = &amp;#39;Number of syllables&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_word_concreteness_diff&amp;#39;] = &amp;#39;Word-concreteness difference&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_cosine_similarity&amp;#39;] = &amp;#39;Language-based similarity &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_visual_rating_diff&amp;#39;] = &amp;#39;Visual-strength difference &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_interstimulus_interval&amp;#39;] = &amp;#39;Stimulus onset asynchrony (SOA) &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_word_concreteness_diff:z_vocabulary_size&amp;#39;] =
&amp;#39;Word-concreteness difference :: Vocabulary size&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_word_concreteness_diff:z_recoded_interstimulus_interval&amp;#39;] =
&amp;#39;Word-concreteness difference : SOA&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_word_concreteness_diff:z_recoded_participant_gender&amp;#39;] =
&amp;#39;Word-concreteness difference : Gender&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_attentional_control:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Attentional control&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_attentional_control:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Attentional control&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_vocabulary_size:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Vocabulary size&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_vocabulary_size:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Vocabulary size&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_participant_gender:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity : Gender&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_participant_gender:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference : Gender&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(KR_summary_semanticpriming_lmerTest$coefficients)[
rownames(KR_summary_semanticpriming_lmerTest$coefficients) ==
&amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
# Next, change the names in the confidence intervals object
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_attentional_control&amp;#39;] = &amp;#39;Attentional control&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_vocabulary_size&amp;#39;] = &amp;#39;Vocabulary size &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_participant_gender&amp;#39;] = &amp;#39;Gender &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_target_word_frequency&amp;#39;] = &amp;#39;Word frequency&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_target_number_syllables&amp;#39;] = &amp;#39;Number of syllables&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_word_concreteness_diff&amp;#39;] = &amp;#39;Word-concreteness difference&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_cosine_similarity&amp;#39;] = &amp;#39;Language-based similarity &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_visual_rating_diff&amp;#39;] = &amp;#39;Visual-strength difference &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_interstimulus_interval&amp;#39;] = &amp;#39;Stimulus onset asynchrony (SOA) &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_word_concreteness_diff:z_vocabulary_size&amp;#39;] =
&amp;#39;Word-concreteness difference :: Vocabulary size&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_word_concreteness_diff:z_recoded_interstimulus_interval&amp;#39;] =
&amp;#39;Word-concreteness difference : SOA&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_word_concreteness_diff:z_recoded_participant_gender&amp;#39;] =
&amp;#39;Word-concreteness difference : Gender&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_attentional_control:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Attentional control&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_attentional_control:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Attentional control&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_vocabulary_size:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity :: Vocabulary size&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_vocabulary_size:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference :: Vocabulary size&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_participant_gender:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity : Gender&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_participant_gender:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference : Gender&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;] =
&amp;#39;Language-based similarity : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;
rownames(confint_semanticpriming_lmerTest)[
rownames(confint_semanticpriming_lmerTest) ==
&amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;] =
&amp;#39;Visual-strength difference : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="frequentist_model_table" class="section level3">
&lt;h3>&lt;code>frequentist_model_table()&lt;/code>&lt;/h3>
&lt;p>The following custom function was used.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Ffrequentist_model_table.R%23L3-L224&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;div id="loading-the-function-from-github" class="section level4">
&lt;h4>Loading the function from GitHub&lt;/h4>
&lt;pre class="r">&lt;code>source(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/raw/main/R_functions/frequentist_model_table.R&amp;#39;)&lt;/code>&lt;/pre>
&lt;/div>
&lt;/div>
&lt;div id="the-function-in-use" class="section level3">
&lt;h3>The function in use&lt;/h3>
&lt;pre class="r">&lt;code># Create table (using custom function from the &amp;#39;R_functions&amp;#39; folder)
frequentist_model_table(
KR_summary_semanticpriming_lmerTest,
confint_semanticpriming_lmerTest,
order_effects = c(&amp;#39;(Intercept)&amp;#39;,
&amp;#39;Attentional control&amp;#39;,
&amp;#39;Vocabulary size &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Gender &amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Word frequency&amp;#39;,
&amp;#39;Number of syllables&amp;#39;,
&amp;#39;Word-concreteness difference&amp;#39;,
&amp;#39;Language-based similarity &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Visual-strength difference &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Stimulus onset asynchrony (SOA) &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Word-concreteness difference :: Vocabulary size&amp;#39;,
&amp;#39;Word-concreteness difference : SOA&amp;#39;,
&amp;#39;Word-concreteness difference : Gender&amp;#39;,
&amp;#39;Language-based similarity :: Attentional control&amp;#39;,
&amp;#39;Visual-strength difference :: Attentional control&amp;#39;,
&amp;#39;Language-based similarity :: Vocabulary size&amp;#39;,
&amp;#39;Visual-strength difference :: Vocabulary size&amp;#39;,
&amp;#39;Language-based similarity : Gender&amp;#39;,
&amp;#39;Visual-strength difference : Gender&amp;#39;,
&amp;#39;Language-based similarity : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;,
&amp;#39;Visual-strength difference : SOA &amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt;&amp;#39;),
# Replace colons in the names of interactions with times symbols
interaction_symbol_x = TRUE,
# No title
caption = NULL) %&amp;gt;%
# Group predictors under headings
pack_rows(&amp;#39;Individual differences&amp;#39;, 2, 4) %&amp;gt;%
pack_rows(&amp;#39;Target-word lexical covariates&amp;#39;, 5, 6) %&amp;gt;%
pack_rows(&amp;#39;Prime--target relationship&amp;#39;, 7, 9) %&amp;gt;%
pack_rows(&amp;#39;Task condition&amp;#39;, 10, 10) %&amp;gt;%
pack_rows(&amp;#39;Interactions&amp;#39;, 11, 21) %&amp;gt;%
# Apply white background to override default shading in HTML output
row_spec(1:21, background = &amp;#39;white&amp;#39;) %&amp;gt;%
# Highlight covariates
row_spec(c(2, 5:7, 11:15), background = &amp;#39;#FFFFF1&amp;#39;) %&amp;gt;%
# Format
kable_classic(full_width = FALSE, html_font = &amp;#39;Cambria&amp;#39;) %&amp;gt;%
# Footnote describing abbreviations, random slopes, etc.
# LaTeX code used to format the text.
footnote(escape = FALSE, threeparttable = TRUE, general_title = &amp;#39;&amp;lt;br&amp;gt;&amp;#39;,
general = paste(&amp;#39;*Note*. &amp;amp;beta; = Estimate based on $z$-scored predictors; *SE* = standard error;&amp;#39;,
&amp;#39;CI = confidence interval. Yellow rows contain covariates. Some interactions are &amp;#39;,
&amp;#39;split over two lines, with the second line indented. &amp;lt;br&amp;gt;&amp;#39;,
&amp;#39;&amp;lt;sup&amp;gt;a&amp;lt;/sup&amp;gt; By-word random slopes were included for this effect.&amp;#39;,
&amp;#39;&amp;lt;sup&amp;gt;b&amp;lt;/sup&amp;gt; By-participant random slopes were included for this effect.&amp;#39;))&lt;/code>&lt;/pre>
&lt;table class="table lightable-classic" style="margin-left: auto; margin-right: auto; font-family: Cambria; width: auto !important; margin-left: auto; margin-right: auto;border-bottom: 0;">
&lt;thead>
&lt;tr>
&lt;th style="text-align:left;text-align: center;">
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
β
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
&lt;i>SE&lt;/i>
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
95% CI
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
&lt;i>t&lt;/i>
&lt;/th>
&lt;th style="text-align:right;text-align: center;">
&lt;i>p&lt;/i>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="text-align:left;background-color: white !important;">
(Intercept)
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.59
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.112
&lt;/td>
&lt;/tr>
&lt;tr grouplength="3">
&lt;td colspan="6" style="border-bottom: 1px solid;">
&lt;strong>Individual differences&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-0.56
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.577
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Vocabulary size &lt;sup>a&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.02
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.987
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Gender &lt;sup>a&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.03
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.979
&lt;/td>
&lt;/tr>
&lt;tr grouplength="2">
&lt;td colspan="6" style="border-bottom: 1px solid;">
&lt;strong>Target-word lexical covariates&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word frequency
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-0.16
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[-0.16, -0.15]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-49.40
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
&amp;lt;.001
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Number of syllables
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.07
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.07, 0.08]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
22.81
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
&amp;lt;.001
&lt;/td>
&lt;/tr>
&lt;tr grouplength="3">
&lt;td colspan="6" style="border-bottom: 1px solid;">
&lt;strong>Prime–target relationship&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.01, 0.02]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
3.48
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.001
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.08
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.08, -0.07]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-22.44
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
&amp;lt;.001
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.01, 0.02]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
4.18
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
&amp;lt;.001
&lt;/td>
&lt;/tr>
&lt;tr grouplength="1">
&lt;td colspan="6" style="border-bottom: 1px solid;">
&lt;strong>Task condition&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Stimulus onset asynchrony (SOA) &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.06
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.04, 0.07]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
7.47
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
&amp;lt;.001
&lt;/td>
&lt;/tr>
&lt;tr grouplength="11">
&lt;td colspan="6" style="border-bottom: 1px solid;">
&lt;strong>Interactions&lt;/strong>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
1.31
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.189
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × SOA
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
2.57
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.010
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Word-concreteness difference × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-0.97
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.332
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Language-based similarity × &lt;br>    Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
-2.46
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.014
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;background-color: #FFFFF1 !important;" indentlevel="1">
Visual-strength difference × &lt;br>    Attentional control
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
[0.00, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
0.24
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;background-color: #FFFFF1 !important;">
.810
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-2.34
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.020
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × &lt;br>    Vocabulary size
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-1.37
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.172
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-0.79
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.433
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × Gender
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
1.46
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.144
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Language-based similarity × SOA &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.01
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[0.00, 0.01]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
3.22
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.001
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="text-align:left;padding-left: 2em;background-color: white !important;" indentlevel="1">
Visual-strength difference × SOA &lt;sup>b&lt;/sup>
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
0.00
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
[-0.01, 0.00]
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
-2.25
&lt;/td>
&lt;td style="text-align:right;background-color: white !important;">
.025
&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;tfoot>
&lt;tr>
&lt;td style="padding: 0; " colspan="100%">
&lt;span style="font-style: italic;">&lt;br>&lt;/span>
&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="padding: 0; " colspan="100%">
&lt;sup>&lt;/sup> &lt;em>Note&lt;/em>. β = Estimate based on &lt;span class="math inline">\(z\)&lt;/span>-scored predictors; &lt;em>SE&lt;/em> = standard error; CI = confidence interval. Yellow rows contain covariates. Some interactions are split over two lines, with the second line indented. &lt;br> &lt;sup>a&lt;/sup> By-word random slopes were included for this effect. &lt;sup>b&lt;/sup> By-participant random slopes were included for this effect.
&lt;/td>
&lt;/tr>
&lt;/tfoot>
&lt;/table>
&lt;div id="shading-specific-rows" class="section level4">
&lt;h4>Shading specific rows&lt;/h4>
&lt;p>Shading specific rows is done differently when the output is PDF, as shown below (see p. 62 in &lt;a href="https://eprints.lancs.ac.uk/id/eprint/177833/6/2022deJuanBernabeuPhD.pdf">Bernabeu, 2022&lt;/a>).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fthesis%2FChapter-3-Study-2.Rmd%23L690-L691&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;/div>
&lt;div id="session-info" class="section level3">
&lt;h3>Session info&lt;/h3>
&lt;p>If you encounter any blockers while reproducing the table using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>, my current session info may be useful.&lt;/p>
&lt;pre class="r">&lt;code>sessionInfo()&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## R version 4.3.2 (2023-10-31 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 11 x64 (build 22621)
##
## Matrix products: default
##
##
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8
## [2] LC_CTYPE=English_United Kingdom.utf8
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United Kingdom.utf8
##
## time zone: Europe/Oslo
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] kableExtra_1.3.4 lmerTest_3.1-3 lme4_1.1-35.1
## [4] Matrix_1.6-4 stringr_1.5.1 tibble_3.2.1
## [7] dplyr_1.1.4 knitr_1.45 xaringanExtra_0.7.0
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.8 utf8_1.2.4 generics_0.1.3
## [4] xml2_1.3.6 blogdown_1.18 stringi_1.8.3
## [7] lattice_0.22-5 digest_0.6.33 magrittr_2.0.3
## [10] evaluate_0.23 grid_4.3.2 bookdown_0.37
## [13] fastmap_1.1.1 jsonlite_1.8.8 httr_1.4.7
## [16] rvest_1.0.3 fansi_1.0.6 viridisLite_0.4.2
## [19] scales_1.3.0 numDeriv_2016.8-1.1 jquerylib_0.1.4
## [22] cli_3.6.2 rlang_1.1.2 munsell_0.5.0
## [25] splines_4.3.2 withr_2.5.2 cachem_1.0.8
## [28] yaml_2.3.8 tools_4.3.2 uuid_1.1-1
## [31] nloptr_2.0.3 minqa_1.2.6 colorspace_2.1-0
## [34] ggplot2_3.4.4 webshot_0.5.5 boot_1.3-28.1
## [37] vctrs_0.6.5 R6_2.5.1 lifecycle_1.0.4
## [40] MASS_7.3-60 pkgconfig_2.0.3 pillar_1.9.0
## [43] bslib_0.6.1 gtable_0.3.4 glue_1.6.2
## [46] Rcpp_1.0.11 systemfonts_1.0.5 xfun_0.41
## [49] tidyselect_1.2.0 rstudioapi_0.15.0 htmltools_0.5.7
## [52] nlme_3.1-164 svglite_2.1.3 rmarkdown_2.25
## [55] compiler_4.3.2&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em>. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Brauer, M., &amp;amp; Curtin, J. J. (2018). Linear mixed-effects models and the analysis of nonindependent data: A unified framework to analyze categorical and continuous independent variables that vary within-subjects and/or within-items. &lt;em>Psychological Methods, 23&lt;/em>(3), 389–411. &lt;a href="https://doi.org/10.1037/met0000159" class="uri">https://doi.org/10.1037/met0000159&lt;/a>&lt;/p>
&lt;p>Kuznetsova, A., Brockhoff, P. B., &amp;amp; Christensen, R. H. B. (2022). &lt;em>Package ’lmerTest’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf" class="uri">https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf&lt;/a>&lt;/p>
&lt;p>Zhu, H. (2022). &lt;em>Package ’kableExtra’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf" class="uri">https://cran.r-project.org/web/packages/kableExtra/kableExtra.pdf&lt;/a>&lt;/p>
&lt;/div></description><category>R</category><category>statistics</category><category>rstats</category><category>lmerTest</category><category>lme4</category><category>confidence intervals</category><category>s</category><category>R</category><category>statistics</category></item><item><title>Plotting two-way interactions from mixed-effects models using alias variables</title><link>https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-alias-variables/</link><pubDate>Mon, 26 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-alias-variables/</guid><description>
&lt;p>Whereas the direction of main effects can be interpreted from the sign of the estimate, the interpretation of interaction effects often requires plots. This task is facilitated by the R package &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf">&lt;code>sjPlot&lt;/code>&lt;/a> (Lüdecke, 2022). In Bernabeu (2022), the sjPlot function called &lt;code>plot_model&lt;/code> served as the basis for the creation of some &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/tree/main/R_functions">custom functions&lt;/a>. One of these functions is &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/R_functions/alias_interaction_plot.R">&lt;code>alias_interaction_plot&lt;/code>&lt;/a>, which allows the plotting of interactions between a continuous variable and a categorical variable. Importantly, the categorical variable is replaced with an alias variable. This feature allows the back-transformation of the categorical variable to facilitate the communication of the results, for instance, when the categorical variable was sum-coded, which has been recommended for mixed-effects models (Brauer &amp;amp; Curtin, 2018).&lt;/p>
&lt;p>Below, we’ll use the function with a model fitted using &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">&lt;code>lmerTest&lt;/code>&lt;/a> (Kuznetsova et al., 2022), although the function also works with several other models (see &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf">sjPlot manual&lt;/a>). The plot can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>.&lt;/p>
&lt;div id="alias-interaction-plot" class="section level2">
&lt;h2>Alias interaction plot&lt;/h2>
&lt;div id="the-function" class="section level3">
&lt;h3>The function&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Falias_interaction_plot.R&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;div id="the-function-in-use" class="section level3">
&lt;h3>The function in use&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Ffrequentist_analysis%2Fsemanticpriming-interactions-with-SOA.R&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;p>&lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/plots/semanticpriming-interactions-with-SOA.pdf">&lt;img src="Screenshot%202022-12-27%20234345.png" width="550" alt="Two-panel interaction plot of predicted reaction time by language-based similarity (a) and visual-strength difference (b), lines coloured by SOA of 200 vs 1200 ms" />&lt;/a>&lt;/p>
&lt;/div>
&lt;div id="references" class="section level3">
&lt;h3>References&lt;/h3>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em>. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Brauer, M., &amp;amp; Curtin, J. J. (2018). Linear mixed-effects models and the analysis of nonindependent data: A unified framework to analyze categorical and continuous independent variables that vary within-subjects and/or within-items. &lt;em>Psychological Methods, 23&lt;/em>(3), 389–411. &lt;a href="https://doi.org/10.1037/met0000159" class="uri">https://doi.org/10.1037/met0000159&lt;/a>&lt;/p>
&lt;p>Kuznetsova, A., Brockhoff, P. B., &amp;amp; Christensen, R. H. B. (2022). &lt;em>Package ’lmerTest’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf" class="uri">https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf&lt;/a>&lt;/p>
&lt;p>Lüdecke, D. (2022). &lt;em>Package ’sjPlot’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf" class="uri">https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf&lt;/a>&lt;/p>
&lt;/div>
&lt;/div></description><category>R</category><category>visualisation</category><category>plotting</category><category>alias</category><category>sjPlot</category><category>linear mixed-effects models</category><category>statistics</category><category>s</category><category>R</category><category>data visualisation</category></item><item><title>Plotting two-way interactions from mixed-effects models using ten or six bins</title><link>https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-ten-or-six-bins/</link><pubDate>Mon, 26 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/plotting-two-way-interactions-from-mixed-effects-models-using-ten-or-six-bins/</guid><description>
&lt;p>Whereas the direction of main effects can be interpreted from the sign of the estimate, the interpretation of interaction effects often requires plots. This task is facilitated by the R package &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf">&lt;code>sjPlot&lt;/code>&lt;/a> (Lüdecke, 2022). In Bernabeu (2022), the sjPlot function called &lt;code>plot_model&lt;/code> served as the basis for the creation of some &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/tree/main/R_functions">custom functions&lt;/a>. Two of these functions are &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/R_functions/deciles_interaction_plot.R">&lt;code>deciles_interaction_plot&lt;/code>&lt;/a> and &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/R_functions/sextiles_interaction_plot.R">&lt;code>sextiles_interaction_plot&lt;/code>&lt;/a>. These functions allow the plotting of interactions between two continuous variables. In the case of &lt;code>deciles_interaction_plot&lt;/code>, one of the variables is divided into ten bins, known as deciles, and the other variable is unchanged. In the case of &lt;code>sextiles_interaction_plot&lt;/code>, one of the variables is divided into six bins, or sextiles, and the other variable is unchanged. Sample size per bin can be printed in the legend, which is particularly useful for research involving individual differences.&lt;/p>
&lt;p>Below, we’ll use these functions with models fitted using &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">&lt;code>lmerTest&lt;/code>&lt;/a> (Kuznetsova et al., 2022), although the functions also work with several other models (see &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf">sjPlot manual&lt;/a>). The plots can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>.&lt;/p>
&lt;div id="deciles-interaction-plot" class="section level2">
&lt;h2>Deciles interaction plot&lt;/h2>
&lt;div id="the-function" class="section level3">
&lt;h3>The function&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Fdeciles_interaction_plot.R%23L3-L209&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;div id="the-function-in-use" class="section level3">
&lt;h3>The function in use&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Ffrequentist_analysis%2Fsemanticpriming-interactions-with-vocabulary-size.R%23L3-L52&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;p>&lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/plots/semanticpriming-interactions-with-vocabulary-size.pdf">&lt;img src="Screenshot%202022-12-27%20234321.png" width="580" alt="Deciles interaction plot: two panels of predicted reaction time by semantic predictors, split by vocabulary-size deciles with per-bin sample sizes" />&lt;/a>&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="sextiles-interaction-plot" class="section level2">
&lt;h2>Sextiles interaction plot&lt;/h2>
&lt;div id="the-function-1" class="section level3">
&lt;h3>The function&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Fsextiles_interaction_plot.R%23L3-L181&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;div id="the-function-in-use-1" class="section level3">
&lt;h3>The function in use&lt;/h3>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Flexicaldecision%2Ffrequentist_analysis%2Flexicaldecision-interactions-with-vocabulary-age.R%23L3-L54&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;p>&lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/lexicaldecision/frequentist_analysis/plots/lexicaldecision-interactions-with-vocabulary-age.pdf">&lt;img src="Screenshot%202022-12-27%20234252.png" width="650" alt="Sextiles interaction plot: two panels of predicted reaction time by word frequency and visual strength, split by vocabulary-age sextiles with per-bin sample sizes" />&lt;/a>&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em>. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Kuznetsova, A., Brockhoff, P. B., &amp;amp; Christensen, R. H. B. (2022). &lt;em>Package ‘lmerTest’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf" class="uri">https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf&lt;/a>&lt;/p>
&lt;p>Lüdecke, D. (2022). &lt;em>Package ‘sjPlot’&lt;/em>. CRAN. &lt;a href="https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf" class="uri">https://cran.r-project.org/web/packages/sjPlot/sjPlot.pdf&lt;/a>&lt;/p>
&lt;/div></description><category>R</category><category>visualisation</category><category>plotting</category><category>deciles</category><category>sextiles</category><category>sjPlot</category><category>linear mixed-effects models</category><category>individual differences</category><category>statistics</category><category>s</category><category>R</category><category>data visualisation</category></item><item><title>Why can't we be friends? Plotting frequentist (lmerTest) and Bayesian (brms) mixed-effects models</title><link>https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/</link><pubDate>Fri, 23 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/index.en_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;p>Frequentist and Bayesian statistics are sometimes regarded as fundamentally different philosophies. Indeed, can both methods qualify as philosophies, or is one of them just a pointless ritual? Is frequentist statistics about &lt;span class="math inline">\(p\)&lt;/span> values only? Are frequentist estimates diametrically opposed to Bayesian posterior distributions? Are confidence intervals and credible intervals irreconcilable? Will R crash if &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">&lt;code>lmerTest&lt;/code>&lt;/a> and &lt;a href="https://cran.r-project.org/web/packages/brms/brms.pdf">&lt;code>brms&lt;/code>&lt;/a> are simultaneously loaded? If only we could fit frequentist and Bayesian models to the same data and plot the results together, we might get a glimpse into these puzzles.&lt;/p>
&lt;p>All the analyses shown below can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>. The combination of the frequentist and the Bayesian estimates in the same plot is achieved using the following custom function from &lt;a href="https://pablobernabeu.github.io/publication/pablo-bernabeu-2022-phd-thesis">Bernabeu (2022)&lt;/a>.&lt;/p>
&lt;div id="visualising-frequentist-and-bayesian-estimates-in-one-plot" class="section level3">
&lt;h3>Visualising frequentist and Bayesian estimates in one plot&lt;/h3>
&lt;p>Both frequentist and Bayesian statistics offer the options of hypothesis testing and parameter estimation (Cumming, 2014; Kruschke &amp;amp; Liddell, 2018; Rouder et al., 2018; Schmalz et al., 2022; Tendeiro &amp;amp; Kiers, 2019, 2022; van Ravenzwaaij &amp;amp; Wagenmakers, 2022). In the statistical analyses conducted by Bernabeu (2022), hypothesis testing was performed within the frequentist framework, whereas parameter estimation was performed within both the frequentist and the Bayesian frameworks (for other examples of the &lt;em>estimation&lt;/em> approach, see Milek et al., 2018; Pregla et al., 2021; Rodríguez-Ferreiro et al., 2020).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2FR_functions%2Ffrequentist_bayesian_plot.R%23L3-L179&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>Let’s load the function from GitHub and put it to the test.&lt;/p>
&lt;div style="height: 800px; border: 0.5px dotted grey; padding: 10px; resize: both; overflow: auto;">
&lt;pre class="r">&lt;code># Presenting the frequentist and the Bayesian estimates in the same plot.
# For this purpose, the frequentist results are merged into a plot from
# brms::mcmc_plot()
source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/main/R_functions/frequentist_bayesian_plot.R&amp;#39;)
# install.packages(&amp;#39;devtools&amp;#39;)
# library(devtools)
# install_version(&amp;#39;tidyverse&amp;#39;, &amp;#39;1.3.1&amp;#39;) # Due to breaking changes, Version 1.3.1 is required.
# install_version(&amp;#39;ggplot2&amp;#39;, &amp;#39;3.3.5&amp;#39;) # Due to breaking changes, Version 3.3.5 is required.
library(tidyverse)
library(ggplot2)
library(Cairo)
# Load frequentist coefficients (estimates and confidence intervals)
KR_summary_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/KR_summary_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))
confint_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/confint_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))
# Below are the default names of the effects
# rownames(KR_summary_semanticpriming_lmerTest$coefficients)
# rownames(confint_semanticpriming_lmerTest)
# Load Bayesian posterior distributions
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/bayesian_analysis/results/semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian.rds?raw=true&amp;#39;)))
# Below are the default names of the effects
# levels(semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian$data$parameter)
# Reorder the components of interactions in the frequentist results to match
# with the order present in the Bayesian results.
rownames(KR_summary_semanticpriming_lmerTest$coefficients) =
rownames(KR_summary_semanticpriming_lmerTest$coefficients) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;,
replacement = &amp;#39;z_cosine_similarity:z_recoded_interstimulus_interval&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;z_visual_rating_diff:z_recoded_interstimulus_interval&amp;#39;)
rownames(confint_semanticpriming_lmerTest) =
rownames(confint_semanticpriming_lmerTest) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;,
replacement = &amp;#39;z_cosine_similarity:z_recoded_interstimulus_interval&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;z_visual_rating_diff:z_recoded_interstimulus_interval&amp;#39;)
# Create a vector containing the names of the effects. This vector will be passed
# to the plotting function.
new_labels =
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian$data$parameter %&amp;gt;%
unique %&amp;gt;%
# Remove the default &amp;#39;b_&amp;#39; from the beginning of each effect
str_remove(&amp;#39;^b_&amp;#39;) %&amp;gt;%
# Put Intercept in parentheses
str_replace(pattern = &amp;#39;Intercept&amp;#39;, replacement = &amp;#39;(Intercept)&amp;#39;) %&amp;gt;%
# First, adjust names of variables (both in main effects and in interactions)
str_replace(pattern = &amp;#39;z_target_word_frequency&amp;#39;,
replacement = &amp;#39;Target-word frequency&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_target_number_syllables&amp;#39;,
replacement = &amp;#39;Number of target-word syllables&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_word_concreteness_diff&amp;#39;,
replacement = &amp;#39;Word-concreteness difference&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_cosine_similarity&amp;#39;,
replacement = &amp;#39;Language-based similarity&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;Visual-strength difference&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_attentional_control&amp;#39;,
replacement = &amp;#39;Attentional control&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_vocabulary_size&amp;#39;,
replacement = &amp;#39;Vocabulary size&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_participant_gender&amp;#39;,
replacement = &amp;#39;Gender&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval&amp;#39;,
replacement = &amp;#39;SOA&amp;#39;) %&amp;gt;%
# Show acronym in main effect of SOA
str_replace(pattern = &amp;#39;^SOA$&amp;#39;,
replacement = &amp;#39;Stimulus onset asynchrony (SOA)&amp;#39;) %&amp;gt;%
# Second, adjust order of effects in interactions. In the output from the model,
# the word-level variables of interest (i.e., &amp;#39;z_cosine_similarity&amp;#39; and
# &amp;#39;z_visual_rating_diff&amp;#39;) sometimes appeared second in their interactions. For
# better consistency, the code below moves those word-level variables (with
# their new names) to the first position in their interactions. Note that the
# order does not affect the results in any way.
sub(&amp;#39;(\\w+.*):(Language-based similarity|Visual-strength difference)&amp;#39;,
&amp;#39;\\2:\\1&amp;#39;,
.) %&amp;gt;%
# Replace colons denoting interactions with times symbols
str_replace(pattern = &amp;#39;:&amp;#39;, replacement = &amp;#39; &amp;amp;times; &amp;#39;)
# Create plot
plot_semanticpriming_frequentist_bayesian_plot_weaklyinformativepriors_exgaussian =
frequentist_bayesian_plot(KR_summary_semanticpriming_lmerTest,
confint_semanticpriming_lmerTest,
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian,
labels = new_labels, interaction_symbol_x = TRUE,
vertical_line_at_x = 0, x_title = &amp;#39;Effect size (&amp;amp;beta;)&amp;#39;,
legend_ncol = 1) +
theme(legend.position = &amp;#39;bottom&amp;#39;)&lt;/code>&lt;/pre>
&lt;/div>
&lt;p>&lt;br>&lt;/p>
&lt;pre class="r">&lt;code>plot_semanticpriming_frequentist_bayesian_plot_weaklyinformativepriors_exgaussian&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models/index.en_files/figure-html/unnamed-chunk-2-1.png" width="672" style="display: block; margin: auto;" alt="Plot comparing frequentist (red intervals) and Bayesian (blue posterior distributions) effect-size estimates per model predictor; estimates largely agree." />&lt;/p>
&lt;p>Frequentist and Bayesian estimates are not so polar opposites, are they? What is more, the larger differences between some estimates are the result of the priors that were set on the corresponding effects. With uninformative priors, the frequentist and the Bayesian estimates are virtually identical.&lt;/p>
&lt;script src='https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Fbayesian_analysis%2Fsemanticpriming_brms_weaklyinformativepriors_exgaussian.R%23L16-L35&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on'>&lt;/script>
&lt;p>Now it’s time to consider in earnest:&lt;/p>
&lt;blockquote>
&lt;p>Is frequentist statistics about &lt;span class="math inline">\(p\)&lt;/span> values only? Are frequentist estimates diametrically opposed to Bayesian posterior distributions? Are confidence intervals and credible intervals irreconcilable? Will R crash if &lt;a href="https://cran.r-project.org/web/packages/lmerTest/lmerTest.pdf">&lt;code>lmerTest&lt;/code>&lt;/a> and &lt;a href="https://cran.r-project.org/web/packages/brms/brms.pdf">&lt;code>brms&lt;/code>&lt;/a> are simultaneously loaded?&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;div id="session-info" class="section level3">
&lt;h3>Session info&lt;/h3>
&lt;p>If you encounter any blockers while reproducing the above analyses using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>, my current session info may be useful. For instance, the legend of the plot may not show if the latest versions of the &lt;code>ggplot2&lt;/code> and the &lt;code>tidyverse&lt;/code> packages are used. Instead, &lt;code>ggplot2 3.3.5&lt;/code> and &lt;code>tidyverse 1.3.1&lt;/code> should be installed using &lt;code>install_version('ggplot2', '3.3.5')&lt;/code> and &lt;code>install_version('tidyverse', '1.3.1')&lt;/code>.&lt;/p>
&lt;pre class="r">&lt;code>sessionInfo()&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## R version 4.2.3 (2023-03-15 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 22621)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8
## [2] LC_CTYPE=English_United Kingdom.utf8
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United Kingdom.utf8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggtext_0.1.2 Cairo_1.6-0 forcats_1.0.0
## [4] stringr_1.5.0 dplyr_1.1.1 purrr_1.0.1
## [7] readr_2.1.4 tidyr_1.3.0 tibble_3.2.1
## [10] ggplot2_3.3.5 tidyverse_1.3.1 knitr_1.42
## [13] xaringanExtra_0.7.0
##
## loaded via a namespace (and not attached):
## [1] Rcpp_1.0.10 lubridate_1.9.2 digest_0.6.31 utf8_1.2.3
## [5] plyr_1.8.8 R6_2.5.1 cellranger_1.1.0 ggridges_0.5.4
## [9] backports_1.4.1 reprex_2.0.2 evaluate_0.21 highr_0.10
## [13] httr_1.4.6 blogdown_1.16 pillar_1.9.0 rlang_1.1.0
## [17] uuid_1.1-0 readxl_1.4.2 rstudioapi_0.14 jquerylib_0.1.4
## [21] rmarkdown_2.21 labeling_0.4.2 munsell_0.5.0 gridtext_0.1.5
## [25] broom_1.0.4 compiler_4.2.3 modelr_0.1.11 xfun_0.38
## [29] pkgconfig_2.0.3 htmltools_0.5.5 tidyselect_1.2.0 bookdown_0.33.3
## [33] fansi_1.0.4 crayon_1.5.2 tzdb_0.4.0 dbplyr_2.3.2
## [37] withr_2.5.0 commonmark_1.9.0 grid_4.2.3 jsonlite_1.8.4
## [41] gtable_0.3.3 lifecycle_1.0.3 DBI_1.1.3 magrittr_2.0.3
## [45] scales_1.2.1 cli_3.4.1 stringi_1.7.12 cachem_1.0.7
## [49] farver_2.1.1 fs_1.6.1 xml2_1.3.3 bslib_0.4.2
## [53] generics_0.1.3 vctrs_0.6.1 tools_4.2.3 glue_1.6.2
## [57] markdown_1.5 hms_1.1.3 fastmap_1.1.1 yaml_2.3.7
## [61] timechange_0.2.0 colorspace_2.1-0 rvest_1.0.3 haven_2.5.2
## [65] sass_0.4.6&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="references" class="section level3">
&lt;h3>References&lt;/h3>
&lt;p>Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: Multilevel analysis and statistical power&lt;/em>. Lancaster University. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795" class="uri">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>&lt;/p>
&lt;p>Cumming, G. (2014). The new statistics: Why and how. &lt;em>Psychological Science, 25&lt;/em>(1), 7–29. &lt;a href="https://doi.org/10.1177/0956797613504966" class="uri">https://doi.org/10.1177/0956797613504966&lt;/a>&lt;/p>
&lt;p>Kruschke, J. K., &amp;amp; Liddell, T. M. (2018). The Bayesian New Statistics: Hypothesis testing, estimation, meta-analysis, and power analysis from a Bayesian perspective. &lt;em>Psychonomic Bulletin &amp;amp; Review, 25&lt;/em>(1), 178–206.&lt;/p>
&lt;p>Milek, A., Butler, E. A., Tackman, A. M., Kaplan, D. M., Raison, C. L., Sbarra, D. A., Vazire, S., &amp;amp; Mehl, M. R. (2018). “Eavesdropping on happiness” revisited: A pooled, multisample replication of the association between life satisfaction and observed daily conversation quantity and quality. &lt;em>Psychological Science, 29&lt;/em>(9), 1451–1462. &lt;a href="https://doi.org/10.1177/0956797618774252" class="uri">https://doi.org/10.1177/0956797618774252&lt;/a>&lt;/p>
&lt;p>Pregla, D., Lissón, P., Vasishth, S., Burchert, F., &amp;amp; Stadie, N. (2021). Variability in sentence comprehension in aphasia in German. &lt;em>Brain and Language, 222&lt;/em>, 105008. &lt;a href="https://doi.org/10.1016/j.bandl.2021.105008" class="uri">https://doi.org/10.1016/j.bandl.2021.105008&lt;/a>&lt;/p>
&lt;p>Rodríguez-Ferreiro, J., Aguilera, M., &amp;amp; Davies, R. (2020). Semantic priming and schizotypal personality: Reassessing the link between thought disorder and enhanced spreading of semantic activation. &lt;em>PeerJ, 8&lt;/em>, e9511. &lt;a href="https://doi.org/10.7717/peerj.9511" class="uri">https://doi.org/10.7717/peerj.9511&lt;/a>&lt;/p>
&lt;p>Rouder, J. N., Haaf, J. M., &amp;amp; Vandekerckhove, J. (2018). Bayesian inference for psychology, part IV: Parameter estimation and Bayes factors. &lt;em>Psychonomic Bulletin &amp;amp; Review, 25&lt;/em>(1), 102–113. &lt;a href="https://doi.org/10.3758/s13423-017-1420-7" class="uri">https://doi.org/10.3758/s13423-017-1420-7&lt;/a>&lt;/p>
&lt;p>Schmalz, X., Biurrun Manresa, J., &amp;amp; Zhang, L. (2021). What is a Bayes factor? &lt;em>Psychological Methods&lt;/em>. &lt;a href="https://doi.org/10.1037/met0000421" class="uri">https://doi.org/10.1037/met0000421&lt;/a>&lt;/p>
&lt;p>Tendeiro, J. N., &amp;amp; Kiers, H. A. L. (2019). A review of issues about null hypothesis Bayesian testing. &lt;em>Psychological Methods, 24&lt;/em>(6), 774–795. &lt;a href="https://doi.org/10.1037/met0000221" class="uri">https://doi.org/10.1037/met0000221&lt;/a>&lt;/p>
&lt;p>Tendeiro, J. N., &amp;amp; Kiers, H. A. L. (2022). On the white, the black, and the many shades of gray in between: Our reply to van Ravenzwaaij and Wagenmakers (2021). &lt;em>Psychological Methods, 27&lt;/em>(3), 466–475. &lt;a href="https://doi.org/10.1037/met0000505" class="uri">https://doi.org/10.1037/met0000505&lt;/a>&lt;/p>
&lt;p>van Ravenzwaaij, D., &amp;amp; Wagenmakers, E.-J. (2022). Advantages masquerading as “issues” in Bayesian hypothesis testing: A commentary on Tendeiro and Kiers (2019). &lt;em>Psychological Methods, 27&lt;/em>(3), 451–465. &lt;a href="https://doi.org/10.1037/met0000415" class="uri">https://doi.org/10.1037/met0000415&lt;/a>&lt;/p>
&lt;/div></description><category>statistics</category><category>Bayesian statistics</category><category>frequentist statistics</category><category>linear-mixed effects models</category><category>lmerTest</category><category>lme4</category><category>brms</category><category>plotting</category><category>data visualisation</category><category>s</category><category>R</category><category>statistics</category></item><item><title>Bayesian workflow: Prior determination, predictive checks and sensitivity analyses</title><link>https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/</link><pubDate>Thu, 22 Dec 2022 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/index.en_files/clipboard/clipboard.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/index.en_files/xaringanExtra-clipboard/xaringanExtra-clipboard.js">&lt;/script>
&lt;script>window.xaringanExtraClipboard(null, {"button":"Copy Code","success":"Copied!","error":"Press Ctrl+C to Copy"})&lt;/script>
&lt;pre class="r">&lt;code>library(dplyr)
library(ggplot2)
library(ggridges)
library(ggtext)
library(patchwork)
library(papaja)&lt;/code>&lt;/pre>
&lt;p>This post presents a code-through of a Bayesian workflow in R, which can be reproduced using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>. The content is &lt;em>closely&lt;/em> based on &lt;span class="citation">Bernabeu (&lt;a href="#ref-bernabeu2022a">2022&lt;/a>)&lt;/span>, which was in turn based on lots of other references. In addition to those, you may wish to consider &lt;span class="citation">Nicenboim et al. (&lt;a href="#ref-nicenboimInprep">n.d.&lt;/a>)&lt;/span>, a book in preparation that is already available online (&lt;a href="https://vasishth.github.io/bayescogsci/book" class="uri">https://vasishth.github.io/bayescogsci/book&lt;/a>).&lt;/p>
&lt;p>In &lt;span class="citation">Bernabeu (&lt;a href="#ref-bernabeu2022a">2022&lt;/a>)&lt;/span>, a Bayesian analysis was performed to complement the estimates that had been obtained in the frequentist analysis. Whereas the goal of the frequentist analysis had been hypothesis testing, for which &lt;span class="math inline">\(p\)&lt;/span> values were used, the goal of the Bayesian analysis was parameter estimation. Accordingly, we estimated the posterior distribution of every effect, without calculating Bayes factors &lt;span class="citation">(for other examples of the same &lt;em>estimation approach&lt;/em>, see &lt;a href="#ref-milekEavesdroppingHappinessRevisited2018">Milek et al., 2018&lt;/a>; &lt;a href="#ref-preglaVariabilitySentenceComprehension2021">Pregla et al., 2021&lt;/a>; &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>; for comparisons between estimation and hypothesis testing, see &lt;a href="#ref-cummingNewStatisticsWhy2014">Cumming, 2014&lt;/a>; &lt;a href="#ref-kruschkeBayesianNewStatistics2018">Kruschke &amp;amp; Liddell, 2018&lt;/a>; &lt;a href="#ref-rouderBayesianInferencePsychology2018">Rouder et al., 2018&lt;/a>; &lt;a href="#ref-schmalzWhatBayesFactor2021">Schmalz et al., 2021&lt;/a>; &lt;a href="#ref-tendeiroReviewIssuesNull2019">Tendeiro &amp;amp; Kiers, 2019&lt;/a>, &lt;a href="#ref-tendeiroOnTheWhite2022">in press&lt;/a>; &lt;a href="#ref-vanravenzwaaijAdvantagesMasqueradingIssues2021">van Ravenzwaaij &amp;amp; Wagenmakers, 2021&lt;/a>)&lt;/span>. In the estimation approach, the estimates are interpreted by considering the position of their credible intervals in relation to the expected effect size. That is, the closer an interval is to an effect size of 0, the smaller the effect of that predictor. For instance, an interval that is symmetrically centred on 0 indicates a very small effect, whereas—in comparison—an interval that does not include 0 at all indicates a far larger effect.&lt;/p>
&lt;p>This analysis served two purposes: first, to ascertain the interpretation of the smaller effects—which were identified as unreliable in the power analyses—, and second, to complement the estimates obtained in the frequentist analysis. The latter purpose was pertinent because the frequentist models presented convergence warnings—even though it must be noted that a previous study found that frequentist and Bayesian estimates were similar despite convergence warnings appearing in the frequentist analysis &lt;span class="citation">(&lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>)&lt;/span>. Furthermore, the complementary analysis was pertinent because the frequentist models presented residual errors that deviated from normality—even though mixed-effects models are fairly robust to such a deviation &lt;span class="citation">(&lt;a href="#ref-kniefViolatingNormalityAssumption2021">Knief &amp;amp; Forstmeier, 2021&lt;/a>; &lt;a href="#ref-schielzethRobustnessLinearMixed2020">Schielzeth et al., 2020&lt;/a>)&lt;/span>. Owing to these precedents, we expected to find broadly similar estimates in the frequentist analyses and in the Bayesian ones. Across studies, each frequentist model has a Bayesian counterpart, with the exception of the secondary analysis performed in Study 2.1 (semantic priming) that included &lt;code>vision-based similarity&lt;/code> as a predictor. The R package ‘brms’, Version 2.17.0, was used for the Bayesian analysis &lt;span class="citation">(&lt;a href="#ref-burknerAdvancedBayesianMultilevel2018">Bürkner, 2018&lt;/a>; &lt;a href="#ref-burknerPackageBrms2022">Bürkner et al., 2022&lt;/a>)&lt;/span>.&lt;/p>
&lt;div id="priors" class="section level2">
&lt;h2>Priors&lt;/h2>
&lt;p>Priors are one of the hardest nuts to crack in Bayesian statistics. First, it can be useful to inspect what priors can be set in the model. Second, it is important to visualise a reasonable set of priors based on the available literature or any other available sources. Third, just before fitting the model, the adequacy of a range of priors should be assessed using prior predictive checks. Fourth, posterior predictive checks were performed to assess the consistency between the observed data and new data predicted by the posterior distributions. Fifth, the influence of the priors on the results should be assessed through a prior sensitivity analysis &lt;span class="citation">(&lt;a href="#ref-leeBayesianCognitiveModeling2014">Lee &amp;amp; Wagenmakers, 2014&lt;/a>; &lt;a href="#ref-schootBayesianStatisticsModelling2021">Van de Schoot et al., 2021&lt;/a>; also see &lt;a href="#ref-bernabeu2022a">Bernabeu, 2022&lt;/a>; &lt;a href="#ref-preglaVariabilitySentenceComprehension2021">Pregla et al., 2021&lt;/a>; &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-stoneInteractionGrammaticallyDistinct2021">Stone et al., 2021&lt;/a>)&lt;/span>.&lt;/p>
&lt;/div>
&lt;div id="checking-what-priors-can-be-set" class="section level2">
&lt;h2>1. Checking what priors can be set&lt;/h2>
&lt;p>The &lt;code>brms::get_prior&lt;/code> function can be used to check what effects in the model can be assigned a prior. The output (see &lt;a href="http://paul-buerkner.github.io/brms/reference/get_prior.html">example&lt;/a>) will include the current (perhaps default) prior on each effect.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Fbayesian_analysis%2Fprior_predictive_checks%2Fsemanticpriming_priorpredictivecheck_informativepriors.R%23L28-L100&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div>
&lt;div id="determining-the-priors" class="section level2">
&lt;h2>2. Determining the priors&lt;/h2>
&lt;p>The priors were established by inspecting the effect sizes obtained in previous studies as well as the effect sizes obtained in our frequentist analyses of the present data (reported in &lt;a href="https://pablobernabeu.github.io/thesis/study-2.1-semantic-priming.html#study-2.1-semantic-priming">Studies 2.1, 2.2 and 2.3&lt;/a>). In the first regard, the previous studies that were considered were selected because the experimental paradigms, variables and analytical procedures they had used were similar to those used in our current studies. Specifically, regarding paradigms, we sought studies that implemented: (I) semantic priming with a lexical decision task—as in Study 2.1—, (II) semantic decision—as in Study 2.2—, or (III) lexical decision—as in Study 2.3. Regarding analytical procedures, we sought studies in which both the dependent and the independent variables were &lt;span class="math inline">\(z\)&lt;/span>-scored. We found two studies that broadly matched these criteria: &lt;span class="citation">Lim et al. (&lt;a href="#ref-lim2020a">2020&lt;/a>)&lt;/span> (see Table 5 therein) and &lt;span class="citation">Pexman &amp;amp; Yap (&lt;a href="#ref-pexman2018a">2018&lt;/a>)&lt;/span> (see Tables 6 and 7 therein). Out of these studies, &lt;span class="citation">Pexman &amp;amp; Yap (&lt;a href="#ref-pexman2018a">2018&lt;/a>)&lt;/span> contained the variables that were most similar to ours, which included vocabulary size (labelled ‘NAART’) and word frequency.&lt;/p>
&lt;p>Based on both these studies and on the &lt;a href="https://pablobernabeu.github.io/thesis/study-2.1-semantic-priming.html#study-2.1-semantic-priming">frequentist analyses&lt;/a>, a range of effect sizes was identified that spanned between β = -0.30 and β = 0.30. This range was centred around 0 as the variables were &lt;span class="math inline">\(z\)&lt;/span>-scored. The bounds of this range were determined by the largest effects, which appeared in &lt;span class="citation">Pexman &amp;amp; Yap (&lt;a href="#ref-pexman2018a">2018&lt;/a>)&lt;/span>. Pexman et al. conducted a semantic decision study, and split the data set into abstract and concrete words. The two largest effects they found were—first—a word concreteness effect in the concrete-words analysis of β = -0.41, and—second—a word concreteness effect in the abstract-words analysis of β = 0.20. Unlike Pexman et al., we did not split the data set into abstract and concrete words, but analysed these sets together. Therefore, we averaged between the aforementioned values, obtaining a range between β = -0.30 and β = 0.30.&lt;/p>
&lt;p>In the results of &lt;span class="citation">Lim et al. (&lt;a href="#ref-lim2020a">2020&lt;/a>)&lt;/span> and &lt;span class="citation">Pexman &amp;amp; Yap (&lt;a href="#ref-pexman2018a">2018&lt;/a>)&lt;/span>, and in our frequentist results, some effects consistently presented a negative polarity (i.e., leading to shorter response times), whereas some other effects were consistently positive. We incorporated the direction of effects into the priors only in cases of large effects that had presented a consistent direction (either positive or negative) in previous studies and in our frequentist analyses in the present studies. These criteria were matched by the following variables: word frequency—with a negative direction, as higher word frequency leads to shorter RTs &lt;span class="citation">(&lt;a href="#ref-brysbaertImpactWordPrevalence2016">Brysbaert et al., 2016&lt;/a>; &lt;a href="#ref-brysbaertWordFrequencyEffect2018a">Brysbaert et al., 2018&lt;/a>; &lt;a href="#ref-lim2020a">Lim et al., 2020&lt;/a>; &lt;a href="#ref-mendesPervasiveEffectWord2021">Mendes &amp;amp; Undorf, 2021&lt;/a>; &lt;a href="#ref-pexman2018a">Pexman &amp;amp; Yap, 2018&lt;/a>)&lt;/span>—, number of letters and number of syllables—both with positive directions &lt;span class="citation">(&lt;a href="#ref-bartonWordlengthEffectReading2014">Barton et al., 2014&lt;/a>; &lt;a href="#ref-beyersmannEvidenceEmbeddedWord2020">Beyersmann et al., 2020&lt;/a>; &lt;a href="#ref-pexman2018a">Pexman &amp;amp; Yap, 2018&lt;/a>)&lt;/span>—, and orthographic Levenshtein distance—with a positive direction &lt;span class="citation">(&lt;a href="#ref-cerniMotorExpertiseTyping2016">Cerni et al., 2016&lt;/a>; &lt;a href="#ref-dijkstraMultilinkComputationalModel2019">Dijkstra et al., 2019&lt;/a>; &lt;a href="#ref-kimEffectsLexicalFeatures2018">Kim et al., 2018&lt;/a>; &lt;a href="#ref-yarkoniMovingColtheartNew2008">Yarkoni et al., 2008&lt;/a>)&lt;/span>. We did not incorporate information about the direction of the word concreteness effect, as this effect can follow different directions in abstract and concrete words &lt;span class="citation">(&lt;a href="#ref-brysbaert2014a">Brysbaert et al., 2014&lt;/a>; &lt;a href="#ref-pexman2018a">Pexman &amp;amp; Yap, 2018&lt;/a>)&lt;/span>, and we analysed both sets of words together. In conclusion, the four predictors that had directional priors were covariates. All the other predictors had priors centred on 0. Last, as a methodological matter, it is noteworthy that most of the psycholinguistic studies applying Bayesian analysis have not incorporated any directional information in priors &lt;span class="citation">(e.g., &lt;a href="#ref-preglaVariabilitySentenceComprehension2021">Pregla et al., 2021&lt;/a>; &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; cf. &lt;a href="#ref-stoneInteractionGrammaticallyDistinct2021">Stone et al., 2021&lt;/a>)&lt;/span>.&lt;/p>
&lt;div id="prior-distributions" class="section level3">
&lt;h3>Prior distributions&lt;/h3>
&lt;p>The choice of priors can influence the results in consequential ways. To assess the extent of this influence, &lt;em>prior sensitivity analyses&lt;/em> have been recommended. These analyses are performed by comparing the effect of more and less strict priors—or, in other words, priors varying in their degree of informativeness. The degree of variation is adjusted through the standard deviation, and the means are not varied &lt;span class="citation">(&lt;a href="#ref-leeBayesianCognitiveModeling2014">Lee &amp;amp; Wagenmakers, 2014&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-schootBayesianStatisticsModelling2021">Van de Schoot et al., 2021&lt;/a>)&lt;/span>.&lt;/p>
&lt;p>In this way, we compared the results obtained using ‘informative’ priors (&lt;span class="math inline">\(SD\)&lt;/span> = 0.1), ‘weakly-informative’ priors (&lt;span class="math inline">\(SD\)&lt;/span> = 0.2) and ‘diffuse’ priors (&lt;span class="math inline">\(SD\)&lt;/span> = 0.3). These standard deviations were chosen so that around 95% of values in the informative priors would fall within our initial range of effect sizes that spanned from -0.30 to 0.30. All priors are illustrated in the figure below. These priors resembled others from previous psycholinguistic studies &lt;span class="citation">(&lt;a href="#ref-preglaVariabilitySentenceComprehension2021">Pregla et al., 2021&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-stoneInteractionGrammaticallyDistinct2021">Stone et al., 2021&lt;/a>)&lt;/span>. For instance, &lt;span class="citation">Stone et al. (&lt;a href="#ref-stoneEffectDecayLexical2020">2020&lt;/a>)&lt;/span> used the following priors: &lt;span class="math inline">\(Normal\)&lt;/span>(0, 0.1), &lt;span class="math inline">\(Normal\)&lt;/span>(0, 0.3) and &lt;span class="math inline">\(Normal\)&lt;/span>(0, 1). The range of standard deviations we used—i.e., 0.1, 0.2 and 0.3—was narrower than those of previous studies because our dependent variable and our predictors were &lt;span class="math inline">\(z\)&lt;/span>-scored, resulting in small estimates and small &lt;span class="math inline">\(SD\)&lt;/span>s &lt;span class="citation">(see &lt;a href="#ref-lim2020a">Lim et al., 2020&lt;/a>; &lt;a href="#ref-pexman2018a">Pexman &amp;amp; Yap, 2018&lt;/a>)&lt;/span>. These priors were used on the fixed effects and on the standard deviation parameters of the fixed effects. For the correlations among the random effects, an &lt;span class="math inline">\(LKJ\)&lt;/span>(2) prior was used &lt;span class="citation">(&lt;a href="#ref-lewandowskiGeneratingRandomCorrelation2009">Lewandowski et al., 2009&lt;/a>)&lt;/span>. This is a ‘regularising’ prior, as it assumes that high correlations among random effects are rare &lt;span class="citation">(also used in &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-stoneInteractionGrammaticallyDistinct2021">Stone et al., 2021&lt;/a>; &lt;a href="#ref-vasishthBayesianDataAnalysis2018">Vasishth et al., 2018&lt;/a>)&lt;/span>.&lt;/p>
&lt;pre class="r">&lt;code># Set seed number to ensure exact reproducibility
# of the random distributions
set.seed(123)
# The code below plots all our types of priors. Each distribution
# contains 10,000 simulations, resulting in 90,000 rows.
# The green vertical rectangle shows the range of plausible effect
# sizes based on previous studies that applied a similar analysis
# (Lim et al., 2020, https://doi.org/10.1177/1747021820906566;
# Pexman &amp;amp; Yap, 2018, https://doi.org/10.1037/xlm0000499) as
# well as on the frequentist analyses of the current data.
priors = data.frame(
informativeness =
as.factor(c(rep(&amp;#39;Informative priors (*SD* = 0.1)&amp;#39;, 30000),
rep(&amp;#39;Weakly-informative priors (*SD* = 0.2)&amp;#39;, 30000),
rep(&amp;#39;Diffuse priors (*SD* = 0.3)&amp;#39;, 30000))),
direction = as.factor(c(rep(&amp;#39;negative&amp;#39;, 10000),
rep(&amp;#39;neutral&amp;#39;, 10000),
rep(&amp;#39;positive&amp;#39;, 10000),
rep(&amp;#39;negative&amp;#39;, 10000),
rep(&amp;#39;neutral&amp;#39;, 10000),
rep(&amp;#39;positive&amp;#39;, 10000),
rep(&amp;#39;negative&amp;#39;, 10000),
rep(&amp;#39;neutral&amp;#39;, 10000),
rep(&amp;#39;positive&amp;#39;, 10000))),
direction_and_distribution =
as.factor(c(rep(&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.1)&amp;#39;, 10000),
rep(&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.1)&amp;#39;, 10000),
rep(&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.1)&amp;#39;, 10000),
rep(&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.2)&amp;#39;, 10000),
rep(&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.2)&amp;#39;, 10000),
rep(&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.2)&amp;#39;, 10000),
rep(&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.3)&amp;#39;, 10000),
rep(&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.3)&amp;#39;, 10000),
rep(&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.3)&amp;#39;, 10000))),
estimate = c(rnorm(10000, m = -0.1, sd = 0.1),
rnorm(10000, m = 0, sd = 0.1),
rnorm(10000, m = 0.1, sd = 0.1),
rnorm(10000, m = -0.1, sd = 0.2),
rnorm(10000, m = 0, sd = 0.2),
rnorm(10000, m = 0.1, sd = 0.2),
rnorm(10000, m = -0.1, sd = 0.3),
rnorm(10000, m = 0, sd = 0.3),
rnorm(10000, m = 0.1, sd = 0.3))
)
# Order factor levels
priors$informativeness =
ordered(priors$informativeness,
levels = c(&amp;#39;Informative priors (*SD* = 0.1)&amp;#39;,
&amp;#39;Weakly-informative priors (*SD* = 0.2)&amp;#39;,
&amp;#39;Diffuse priors (*SD* = 0.3)&amp;#39;))
priors$direction =
ordered(priors$direction,
levels = c(&amp;#39;negative&amp;#39;, &amp;#39;neutral&amp;#39;, &amp;#39;positive&amp;#39;))
priors$direction_and_distribution =
ordered(priors$direction_and_distribution,
levels = c(&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.1)&amp;#39;,
&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.1)&amp;#39;,
&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.1)&amp;#39;,
&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.2)&amp;#39;,
&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.2)&amp;#39;,
&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.2)&amp;#39;,
&amp;#39;Negative (*M* = -0.1)&amp;lt;br&amp;gt;*Normal*(-0.1, 0.3)&amp;#39;,
&amp;#39;Neutral (*M* = 0)&amp;lt;br&amp;gt;*Normal*(0, 0.3)&amp;#39;,
&amp;#39;Positive (*M* = 0.1)&amp;lt;br&amp;gt;*Normal*(0.1, 0.3)&amp;#39;))
# PLOT zone
colours = c(&amp;#39;#7276A2&amp;#39;, &amp;#39;black&amp;#39;, &amp;#39;#A27272&amp;#39;)
fill_colours = c(&amp;#39;#CCCBE7&amp;#39;, &amp;#39;#D7D7D7&amp;#39;, &amp;#39;#E7CBCB&amp;#39;)
# Initialise plot (`aes` specified separately to allow
# use of `geom_rect` at the end)
ggplot() +
# Turn to the distributions
stat_density_ridges(data = priors,
aes(x = estimate, y = direction_and_distribution,
color = direction, fill = direction),
geom = &amp;#39;density_ridges_gradient&amp;#39;, alpha = 0.7,
jittered_points = TRUE, quantile_lines = TRUE,
quantiles = c(0.025, 0.975), show.legend = F) +
scale_color_manual(values = colours) +
scale_fill_manual(values = fill_colours) +
# Adjust X axis to the random distributions obtained
scale_x_continuous(limits = c(min(priors$estimate),
max(priors$estimate)),
n.breaks = 6, expand = c(0.04, 0.04)) +
scale_y_discrete(expand = expansion(add = c(0.18, 1.9))) +
# Facets containing the three models varying in informativeness
facet_wrap(vars(informativeness), scales = &amp;#39;free&amp;#39;, dir = &amp;#39;v&amp;#39;) +
# Vertical line at x = 0
geom_vline(xintercept = 0, linetype = &amp;#39;dashed&amp;#39;, color = &amp;#39;grey50&amp;#39;) +
xlab(&amp;#39;Effect size (&amp;amp;beta;)&amp;#39;) +
ylab(&amp;#39;Direction of the prior and corresponding distribution&amp;#39;) +
theme_minimal() +
theme(axis.title.x = ggtext::element_markdown(size = 12, margin = margin(t = 9)),
axis.text.x = ggtext::element_markdown(size = 11, margin = margin(t = 4)),
axis.title.y = ggtext::element_markdown(size = 12, margin = margin(r = 9)),
axis.text.y = ggtext::element_markdown(lineheight = 1.6, colour = colours),
strip.background = element_rect(fill = &amp;#39;grey98&amp;#39;, colour = &amp;#39;grey90&amp;#39;,
linetype = &amp;#39;solid&amp;#39;),
strip.text = element_markdown(size = 11, margin = margin(t = 7, b = 7)),
panel.spacing.y = unit(9, &amp;#39;pt&amp;#39;), panel.grid.minor = element_blank(),
plot.margin = margin(8, 8, 9, 8)
) +
# Shaded rectangle containing range of previous effects
geom_rect(data = data.frame(x = 1), xmin = -0.3, xmax = 0.3,
ymin = -Inf, ymax = Inf, fill = &amp;#39;darkgreen&amp;#39;, alpha = .3)&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/index.en_files/figure-html/bayesian-priors-1.png" width="480" style="display: block; margin: auto;" alt="Grid of normal priors (positive, neutral, negative; SD 0.1-0.3) over effect size, with green band marking plausible effects" />&lt;/p>
&lt;blockquote>
&lt;p>Priors used in the three studies. The green vertical rectangle shows the range of plausible effect sizes based on previous studies and on our frequentist analyses. In the informative priors, around 95% of the values fall within the range.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;br>&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="prior-predictive-checks" class="section level2">
&lt;h2>3. Prior predictive checks&lt;/h2>
&lt;p>The adequacy of each of these priors was assessed by performing prior predictive checks, in which we compared the observed data to the predictions of the model &lt;span class="citation">(&lt;a href="#ref-schootBayesianStatisticsModelling2021">Van de Schoot et al., 2021&lt;/a>)&lt;/span>. Furthermore, in these checks we also tested the adequacy of two model-wide distributions: the traditional Gaussian distribution (default in most analyses) and an exponentially modified Gaussian—dubbed ‘ex-Gaussian’—distribution &lt;span class="citation">(&lt;a href="#ref-matzkePsychologicalInterpretationExGaussian2009">Matzke &amp;amp; Wagenmakers, 2009&lt;/a>)&lt;/span>. The ex-Gaussian distribution was considered because the residual errors of the frequentist models were not normally distributed &lt;span class="citation">(&lt;a href="#ref-loTransformNotTransform2015">Lo &amp;amp; Andrews, 2015&lt;/a>)&lt;/span>, and because this distribution was found to be more appropriate than the Gaussian one in a previous, related study &lt;span class="citation">(see supplementary materials of &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>)&lt;/span>. The ex-Gaussian distribution had an identity link function, which preserves the interpretability of the coefficients, as opposed to a transformation applied directly to the dependent variable &lt;span class="citation">(&lt;a href="#ref-loTransformNotTransform2015">Lo &amp;amp; Andrews, 2015&lt;/a>)&lt;/span>. The results of these prior predictive checks revealed that the priors were adequate, and that the ex-Gaussian distribution was more appropriate than the Gaussian one, converging with &lt;span class="citation">Rodríguez-Ferreiro et al. (&lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">2020&lt;/a>)&lt;/span>. Therefore, the ex-Gaussian distribution was used in the final models.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Fbayesian_analysis%2Fprior_predictive_checks%2Fsemanticpriming_priorpredictivecheck_informativepriors.R%23L105-L235&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;div id="models-with-a-gaussian-distribution" class="section level3">
&lt;h3>Models with a Gaussian distribution&lt;/h3>
&lt;p>The figures below show the prior predictive checks for the Gaussian models. These plots show the maximum, mean and minimum values of the observed data (&lt;span class="math inline">\(y\)&lt;/span>) and those of the predicted distribution (&lt;span class="math inline">\(y_{rep}\)&lt;/span>, which stands for replications of the outcome). The way of interpreting these plots is by comparing the observed data to the predicted distribution. The specifics of this comparison vary across the three plots. First, in the upper plot, which shows the maximum values, the ideal scenario would show the observed maximum value (&lt;span class="math inline">\(y\)&lt;/span>) overlapping with the maximum value of the predicted distribution (&lt;span class="math inline">\(y_{rep}\)&lt;/span>). Second, in the middle plot, showing the mean values, the ideal scenario would show the observed mean value (&lt;span class="math inline">\(y\)&lt;/span>) overlapping with the mean value of the predicted distribution (&lt;span class="math inline">\(y_{rep}\)&lt;/span>). Last, in the lower plot, which shows the minimum values, the ideal scenario would have the observed minimum value (&lt;span class="math inline">\(y\)&lt;/span>) overlapping with the minimum value of the predicted distribution (&lt;span class="math inline">\(y_{rep}\)&lt;/span>). While the overlap need not be absolute, the closer the observed and the predicted values are on the X axis, the better. As such, the three predictive checks below—corresponding to models that used the default Gaussian distribution—show that the priors fitted the data acceptably but not very well.&lt;/p>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_informativepriors.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the Gaussian, informative-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;br>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_weaklyinformativepriors.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the Gaussian, weakly-informative-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;br>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_diffusepriors.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the Gaussian, diffuse-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;/div>
&lt;div id="models-with-an-exponentially-modified-gaussian-i.e.-ex-gaussian-distribution" class="section level3">
&lt;h3>Models with an exponentially-modified Gaussian (i.e., ex-Gaussian) distribution&lt;/h3>
&lt;p>In contrast to the above results, the figures below demonstrate that, when an ex-Gaussian distribution was used, the priors fitted the data far better, which converged with the results of a similar comparison performed by Rodríguez-Ferreiro et al. (2020; see supplementary materials of the latter study).&lt;/p>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_informativepriors_exgaussian.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the ex-Gaussian, informative-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;br>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_weaklyinformativepriors_exgaussian.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the ex-Gaussian, weakly-informative-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;br>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/prior_predictive_checks/plots/semanticpriming_priorpredictivecheck_diffusepriors_exgaussian.pdf" width="100%" height="740" type="application/pdf">
&lt;blockquote>
&lt;p>Prior predictive checks for the ex-Gaussian, diffuse-prior model from the semantic priming study. &lt;span class="math inline">\(y\)&lt;/span> = observed data; &lt;span class="math inline">\(y_{rep}\)&lt;/span> = predicted data.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;br>&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="posterior-predictive-checks" class="section level2">
&lt;h2>4. Posterior predictive checks&lt;/h2>
&lt;p>Based on the results from the prior predictive checks, the ex-Gaussian distribution was used in the final models. Next, posterior predictive checks were performed to assess the consistency between the observed data and new data predicted by the posterior distributions &lt;span class="citation">(&lt;a href="#ref-schootBayesianStatisticsModelling2021">Van de Schoot et al., 2021&lt;/a>)&lt;/span>. The figure below presents the posterior predictive checks for the latter models. The interpretation of these plots is simple: the distributions of the observed (&lt;span class="math inline">\(y\)&lt;/span>) and the predicted data (&lt;span class="math inline">\(y_{rep}\)&lt;/span>) should be as similar as possible. As such, the plots below suggest that the results are trustworthy.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Flanguage-sensorimotor-simulation-PhD-thesis%2Fblob%2Fmain%2Fsemanticpriming%2Fbayesian_analysis%2Fposterior_predictive_checks%2Fsemanticpriming_posteriorpredictivechecks.R%23L3-L68&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;embed src="https://pablobernabeu.github.io/language-sensorimotor-simulation-PhD-thesis/semanticpriming/bayesian_analysis/posterior_predictive_checks/plots/semanticpriming_posteriorpredictivechecks_allpriors_exgaussian.pdf" width="100%" height="360" type="application/pdf">
&lt;blockquote>
&lt;p>Posterior predictive checks for the (ex-Gaussian) models from the semantic priming study. The observed data (&lt;span class="math inline">\(y\)&lt;/span>) and the predicted data (&lt;span class="math inline">\(y_{rep}\)&lt;/span>) almost entirely overlap with each other, demonstrating a very good fit.&lt;/p>
&lt;/blockquote>
&lt;p>&lt;br>&lt;/p>
&lt;/div>
&lt;div id="prior-sensitivity-analysis" class="section level2">
&lt;h2>5. Prior sensitivity analysis&lt;/h2>
&lt;p>In the main analysis, the informative, weakly-informative and diffuse priors were used in separate models. In other words, in each model, all priors had the same degree of informativeness &lt;span class="citation">(as done in &lt;a href="#ref-preglaVariabilitySentenceComprehension2021">Pregla et al., 2021&lt;/a>; &lt;a href="#ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020">Rodríguez-Ferreiro et al., 2020&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-stoneInteractionGrammaticallyDistinct2021">Stone et al., 2021&lt;/a>)&lt;/span>. In this way, a prior sensitivity analysis was performed to acknowledge the likely influence of the priors on the posterior distributions—that is, on the results &lt;span class="citation">(&lt;a href="#ref-leeBayesianCognitiveModeling2014">Lee &amp;amp; Wagenmakers, 2014&lt;/a>; &lt;a href="#ref-stoneEffectDecayLexical2020">Stone et al., 2020&lt;/a>; &lt;a href="#ref-schootBayesianStatisticsModelling2021">Van de Schoot et al., 2021&lt;/a>)&lt;/span>.&lt;/p>
&lt;p>We’ll first load a &lt;a href="https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/R_functions/frequentist_bayesian_plot.R">custom function (&lt;code>frequentist_bayesian_plot&lt;/code>)&lt;/a> from GitHub.&lt;/p>
&lt;pre class="r">&lt;code>source(&amp;#39;https://raw.githubusercontent.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/main/R_functions/frequentist_bayesian_plot.R&amp;#39;)&lt;/code>&lt;/pre>
&lt;div style="height: 800px; border: 0.5px dotted grey; padding: 10px; resize: both; overflow: auto;">
&lt;pre class="r">&lt;code># Presenting the frequentist and the Bayesian estimates in the same plot.
# For this purpose, the frequentist results are merged into a plot from
# brms::mcmc_plot()
# install.packages(&amp;#39;devtools&amp;#39;)
# library(devtools)
# install_version(&amp;#39;tidyverse&amp;#39;, &amp;#39;1.3.1&amp;#39;) # Due to breaking changes, Version 1.3.1 is required.
# install_version(&amp;#39;ggplot2&amp;#39;, &amp;#39;5.3.5&amp;#39;) # Due to breaking changes, Version 5.3.5 is required.
library(tidyverse)
library(ggplot2)
library(Cairo)
# Load frequentist coefficients (estimates and confidence intervals)
KR_summary_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/KR_summary_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))
confint_semanticpriming_lmerTest =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/frequentist_analysis/results/confint_semanticpriming_lmerTest.rds?raw=true&amp;#39;)))
# Below are the default names of the effects
# rownames(KR_summary_semanticpriming_lmerTest$coefficients)
# rownames(confint_semanticpriming_lmerTest)
# Load Bayesian posterior distributions
semanticpriming_posteriordistributions_informativepriors_exgaussian =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/bayesian_analysis/results/semanticpriming_posteriordistributions_informativepriors_exgaussian.rds?raw=true&amp;#39;)))
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/bayesian_analysis/results/semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian.rds?raw=true&amp;#39;)))
semanticpriming_posteriordistributions_diffusepriors_exgaussian =
readRDS(gzcon(url(&amp;#39;https://github.com/pablobernabeu/language-sensorimotor-simulation-PhD-thesis/blob/main/semanticpriming/bayesian_analysis/results/semanticpriming_posteriordistributions_diffusepriors_exgaussian.rds?raw=true&amp;#39;)))
# Below are the default names of the effects
# levels(semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian$data$parameter)
# Reorder the components of interactions in the frequentist results to match
# with the order present in the Bayesian results.
rownames(KR_summary_semanticpriming_lmerTest$coefficients) =
rownames(KR_summary_semanticpriming_lmerTest$coefficients) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;,
replacement = &amp;#39;z_cosine_similarity:z_recoded_interstimulus_interval&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;z_visual_rating_diff:z_recoded_interstimulus_interval&amp;#39;)
rownames(confint_semanticpriming_lmerTest) =
rownames(confint_semanticpriming_lmerTest) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_cosine_similarity&amp;#39;,
replacement = &amp;#39;z_cosine_similarity:z_recoded_interstimulus_interval&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval:z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;z_visual_rating_diff:z_recoded_interstimulus_interval&amp;#39;)
# Create a vector containing the names of the effects. This vector will be passed
# to the plotting function.
new_labels =
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian$data$parameter %&amp;gt;%
unique %&amp;gt;%
# Remove the default &amp;#39;b_&amp;#39; from the beginning of each effect
str_remove(&amp;#39;^b_&amp;#39;) %&amp;gt;%
# Put Intercept in parentheses
str_replace(pattern = &amp;#39;Intercept&amp;#39;, replacement = &amp;#39;(Intercept)&amp;#39;) %&amp;gt;%
# First, adjust names of variables (both in main effects and in interactions)
str_replace(pattern = &amp;#39;z_target_word_frequency&amp;#39;,
replacement = &amp;#39;Target-word frequency&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_target_number_syllables&amp;#39;,
replacement = &amp;#39;Number of target-word syllables&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_word_concreteness_diff&amp;#39;,
replacement = &amp;#39;Word-concreteness difference&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_cosine_similarity&amp;#39;,
replacement = &amp;#39;Language-based similarity&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_visual_rating_diff&amp;#39;,
replacement = &amp;#39;Visual-strength difference&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_attentional_control&amp;#39;,
replacement = &amp;#39;Attentional control&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_vocabulary_size&amp;#39;,
replacement = &amp;#39;Vocabulary size&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_participant_gender&amp;#39;,
replacement = &amp;#39;Gender&amp;#39;) %&amp;gt;%
str_replace(pattern = &amp;#39;z_recoded_interstimulus_interval&amp;#39;,
replacement = &amp;#39;SOA&amp;#39;) %&amp;gt;%
# Show acronym in main effect of SOA
str_replace(pattern = &amp;#39;^SOA$&amp;#39;,
replacement = &amp;#39;Stimulus onset asynchrony (SOA)&amp;#39;) %&amp;gt;%
# Second, adjust order of effects in interactions. In the output from the model,
# the word-level variables of interest (i.e., &amp;#39;z_cosine_similarity&amp;#39; and
# &amp;#39;z_visual_rating_diff&amp;#39;) sometimes appeared second in their interactions. For
# better consistency, the code below moves those word-level variables (with
# their new names) to the first position in their interactions. Note that the
# order does not affect the results in any way.
sub(&amp;#39;(\\w+.*):(Language-based similarity|Visual-strength difference)&amp;#39;,
&amp;#39;\\2:\\1&amp;#39;,
.) %&amp;gt;%
# Replace colons denoting interactions with times symbols
str_replace(pattern = &amp;#39;:&amp;#39;, replacement = &amp;#39; &amp;amp;times; &amp;#39;)
# Create plots, beginning with the informative-prior model
plot_semanticpriming_frequentist_bayesian_plot_informativepriors_exgaussian =
frequentist_bayesian_plot(KR_summary_semanticpriming_lmerTest,
confint_semanticpriming_lmerTest,
semanticpriming_posteriordistributions_informativepriors_exgaussian,
labels = new_labels, interaction_symbol_x = TRUE,
vertical_line_at_x = 0, x_title = &amp;#39;Effect size (&amp;amp;beta;)&amp;#39;,
x_axis_labels = 3, note_frequentist_no_prior = TRUE) +
ggtitle(&amp;#39;Prior *SD* = 0.1&amp;#39;)
#####
plot_semanticpriming_frequentist_bayesian_plot_weaklyinformativepriors_exgaussian =
frequentist_bayesian_plot(KR_summary_semanticpriming_lmerTest,
confint_semanticpriming_lmerTest,
semanticpriming_posteriordistributions_weaklyinformativepriors_exgaussian,
labels = new_labels, interaction_symbol_x = TRUE,
vertical_line_at_x = 0, x_title = &amp;#39;Effect size (&amp;amp;beta;)&amp;#39;,
x_axis_labels = 3, note_frequentist_no_prior = TRUE) +
ggtitle(&amp;#39;Prior *SD* = 0.2&amp;#39;) +
theme(axis.text.y = element_blank())
#####
plot_semanticpriming_frequentist_bayesian_plot_diffusepriors_exgaussian =
frequentist_bayesian_plot(KR_summary_semanticpriming_lmerTest,
confint_semanticpriming_lmerTest,
semanticpriming_posteriordistributions_diffusepriors_exgaussian,
labels = new_labels, interaction_symbol_x = TRUE,
vertical_line_at_x = 0, x_title = &amp;#39;Effect size (&amp;amp;beta;)&amp;#39;,
x_axis_labels = 3, note_frequentist_no_prior = TRUE) +
ggtitle(&amp;#39;Prior *SD* = 0.3&amp;#39;) +
theme(axis.text.y = element_blank())&lt;/code>&lt;/pre>
&lt;/div>
&lt;p>&lt;br>&lt;/p>
&lt;p>The figure below presents the posterior distribution of each effect in each model. The frequentist estimates are also shown to facilitate the comparison.&lt;/p>
&lt;pre class="r">&lt;code>plot_semanticpriming_frequentist_bayesian_plot_informativepriors_exgaussian +
plot_semanticpriming_frequentist_bayesian_plot_weaklyinformativepriors_exgaussian +
plot_semanticpriming_frequentist_bayesian_plot_diffusepriors_exgaussian +
plot_layout(ncol = 3, guides = &amp;#39;collect&amp;#39;) &amp;amp; theme(legend.position = &amp;#39;bottom&amp;#39;)&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2022/bayesian-workflow-prior-determination-predictive-checks-and-sensitivity-analyses/index.en_files/figure-html/unnamed-chunk-4-1.png" width="768" style="display: block; margin: auto;" alt="Forest plot of effect-size estimates per predictor comparing frequentist (red) and Bayesian (blue) analyses, across prior SD 0.1, 0.2, 0.3" />&lt;/p>
&lt;blockquote>
&lt;p>Estimates from the frequentist analysis (in red) and from the Bayesian analysis (in blue) for the semantic priming study, in each model. The frequentist means (represented by points) are flanked by 95% confidence intervals. The Bayesian means (represented by vertical lines) are flanked by 95% credible intervals in light blue (in some cases, the interval is occluded by the bar of the mean)&lt;/p>
&lt;/blockquote>
&lt;p>&lt;br>&lt;/p>
&lt;p>A blog post on the &lt;a href="https://pablobernabeu.github.io/2022/why-can-t-we-be-friends-plotting-frequentist-lmertest-and-bayesian-brms-mixed-effects-models">frequentist-Bayesian plots is also available&lt;/a>.&lt;/p>
&lt;div id="session-info" class="section level3">
&lt;h3>Session info&lt;/h3>
&lt;p>If you encounter any blockers while reproduce the above analyses using the materials at &lt;a href="https://osf.io/gt5uf" class="uri">https://osf.io/gt5uf&lt;/a>, my current session info may be useful. For instance, the legend of the last plot may not show if the latest versions of the &lt;code>ggplot2&lt;/code> and the &lt;code>tidyverse&lt;/code> packages are used. Instead, &lt;code>ggplot2 3.3.5&lt;/code> and &lt;code>tidyverse 1.3.1&lt;/code> should be installed using &lt;code>install_version('ggplot2', '3.3.5')&lt;/code> and &lt;code>install_version('tidyverse', '1.3.1')&lt;/code>.&lt;/p>
&lt;pre class="r">&lt;code>sessionInfo()&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## R version 4.2.3 (2023-03-15 ucrt)
## Platform: x86_64-w64-mingw32/x64 (64-bit)
## Running under: Windows 10 x64 (build 22621)
##
## Matrix products: default
##
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8
## [2] LC_CTYPE=English_United Kingdom.utf8
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United Kingdom.utf8
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] Cairo_1.6-0 forcats_1.0.0 stringr_1.5.0
## [4] purrr_1.0.1 readr_2.1.4 tidyr_1.3.0
## [7] tibble_3.2.1 tidyverse_1.3.1 papaja_0.1.1
## [10] tinylabels_0.2.3 patchwork_1.1.2 ggtext_0.1.2
## [13] ggridges_0.5.4 ggplot2_3.3.5 dplyr_1.1.1
## [16] knitr_1.42 xaringanExtra_0.7.0
##
## loaded via a namespace (and not attached):
## [1] fs_1.6.1 lubridate_1.9.2 insight_0.19.2 httr_1.4.6
## [5] tools_4.2.3 backports_1.4.1 bslib_0.4.2 utf8_1.2.3
## [9] R6_2.5.1 DBI_1.1.3 colorspace_2.1-0 withr_2.5.0
## [13] tidyselect_1.2.0 emmeans_1.8.7 compiler_4.2.3 cli_3.4.1
## [17] rvest_1.0.3 xml2_1.3.3 sandwich_3.0-2 labeling_0.4.2
## [21] bookdown_0.33.3 bayestestR_0.13.1 sass_0.4.6 scales_1.2.1
## [25] mvtnorm_1.1-3 commonmark_1.9.0 digest_0.6.31 rmarkdown_2.21
## [29] pkgconfig_2.0.3 htmltools_0.5.5 dbplyr_2.3.2 fastmap_1.1.1
## [33] highr_0.10 rlang_1.1.0 readxl_1.4.2 rstudioapi_0.14
## [37] jquerylib_0.1.4 farver_2.1.1 generics_0.1.3 zoo_1.8-11
## [41] jsonlite_1.8.4 magrittr_2.0.3 parameters_0.21.1 Matrix_1.6-1
## [45] Rcpp_1.0.10 munsell_0.5.0 fansi_1.0.4 lifecycle_1.0.3
## [49] stringi_1.7.12 multcomp_1.4-23 yaml_2.3.7 MASS_7.3-60
## [53] plyr_1.8.8 grid_4.2.3 crayon_1.5.2 lattice_0.21-8
## [57] haven_2.5.2 splines_4.2.3 gridtext_0.1.5 hms_1.1.3
## [61] pillar_1.9.0 uuid_1.1-0 markdown_1.5 estimability_1.4.1
## [65] effectsize_0.8.3 codetools_0.2-19 reprex_2.0.2 glue_1.6.2
## [69] evaluate_0.21 blogdown_1.16 modelr_0.1.11 vctrs_0.6.1
## [73] tzdb_0.4.0 cellranger_1.1.0 gtable_0.3.3 datawizard_0.8.0
## [77] cachem_1.0.7 xfun_0.38 xtable_1.8-4 broom_1.0.4
## [81] survival_3.5-7 timechange_0.2.0 TH.data_1.1-1&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="references" class="section level3">
&lt;h3>References&lt;/h3>
&lt;div id="refs" class="references csl-bib-body" line-spacing="2">
&lt;div id="ref-bartonWordlengthEffectReading2014" class="csl-entry">
Barton, J. J. S., Hanif, H. M., Eklinder Björnström, L., &amp;amp; Hills, C. (2014). The word-length effect in reading: &lt;span>A&lt;/span> review. &lt;em>Cognitive Neuropsychology&lt;/em>, &lt;em>31&lt;/em>(5-6), 378–412. &lt;a href="https://doi.org/10.1080/02643294.2014.895314">https://doi.org/10.1080/02643294.2014.895314&lt;/a>
&lt;/div>
&lt;div id="ref-bernabeu2022a" class="csl-entry">
Bernabeu, P. (2022). &lt;em>Language and sensorimotor simulation in conceptual processing: &lt;span>Multilevel&lt;/span> analysis and statistical power&lt;/em>. &lt;span>Lancaster University&lt;/span>. &lt;a href="https://doi.org/10.17635/lancaster/thesis/1795">https://doi.org/10.17635/lancaster/thesis/1795&lt;/a>
&lt;/div>
&lt;div id="ref-beyersmannEvidenceEmbeddedWord2020" class="csl-entry">
Beyersmann, E., Grainger, J., &amp;amp; Taft, M. (2020). Evidence for embedded word length effects in complex nonwords. &lt;em>Language, Cognition and Neuroscience&lt;/em>, &lt;em>35&lt;/em>(2), 235–245. &lt;a href="https://doi.org/10.1080/23273798.2019.1659989">https://doi.org/10.1080/23273798.2019.1659989&lt;/a>
&lt;/div>
&lt;div id="ref-brysbaertWordFrequencyEffect2018a" class="csl-entry">
Brysbaert, M., Mandera, P., &amp;amp; Keuleers, E. (2018). The word frequency effect in word processing: &lt;span>An&lt;/span> updated review. &lt;em>Current Directions in Psychological Science&lt;/em>, &lt;em>27&lt;/em>(1), 45–50. &lt;a href="https://doi.org/10.1177/0963721417727521">https://doi.org/10.1177/0963721417727521&lt;/a>
&lt;/div>
&lt;div id="ref-brysbaertImpactWordPrevalence2016" class="csl-entry">
Brysbaert, M., Stevens, M., Mandera, P., &amp;amp; Keuleers, E. (2016). The impact of word prevalence on lexical decision times: &lt;span>Evidence&lt;/span> from the &lt;span>Dutch Lexicon Project&lt;/span> 2. &lt;em>Journal of Experimental Psychology: Human Perception and Performance&lt;/em>, &lt;em>42&lt;/em>(3), 441–458. &lt;a href="https://doi.org/10.1037/xhp0000159">https://doi.org/10.1037/xhp0000159&lt;/a>
&lt;/div>
&lt;div id="ref-brysbaert2014a" class="csl-entry">
Brysbaert, M., Warriner, A. B., &amp;amp; Kuperman, V. (2014). Concreteness ratings for 40 thousand generally known &lt;span>English&lt;/span> word lemmas. &lt;em>Behavior Research Methods&lt;/em>, &lt;em>46&lt;/em>, 904–911. &lt;a href="https://doi.org/10.3758/s13428-013-0403-5">https://doi.org/10.3758/s13428-013-0403-5&lt;/a>
&lt;/div>
&lt;div id="ref-burknerAdvancedBayesianMultilevel2018" class="csl-entry">
Bürkner, P.-C. (2018). Advanced &lt;span>Bayesian&lt;/span> multilevel modeling with the &lt;span>R&lt;/span> package &lt;span class="nocase">brms&lt;/span>. &lt;em>The R Journal&lt;/em>, &lt;em>10&lt;/em>(1), 395–411. &lt;a href="https://journal.r-project.org/archive/2018/RJ-2018-017/index.html">https://journal.r-project.org/archive/2018/RJ-2018-017/index.html&lt;/a>
&lt;/div>
&lt;div id="ref-burknerPackageBrms2022" class="csl-entry">
Bürkner, P.-C., Gabry, J., Weber, S., Johnson, A., Modrak, M., Badr, H. S., Weber, F., Ben-Shachar, M. S., &amp;amp; Rabel, H. (2022). &lt;em>Package ’&lt;span class="nocase">brms&lt;/span>’&lt;/em>. &lt;span>CRAN&lt;/span>. &lt;a href="https://cran.r-project.org/web/packages/brms/brms.pdf">https://cran.r-project.org/web/packages/brms/brms.pdf&lt;/a>
&lt;/div>
&lt;div id="ref-cerniMotorExpertiseTyping2016" class="csl-entry">
Cerni, T., Velay, J.-L., Alario, F.-X., Vaugoyeau, M., &amp;amp; Longcamp, M. (2016). Motor expertise for typing impacts lexical decision performance. &lt;em>Trends in Neuroscience and Education&lt;/em>, &lt;em>5&lt;/em>(3), 130–138. &lt;a href="https://doi.org/10.1016/j.tine.2016.07.007">https://doi.org/10.1016/j.tine.2016.07.007&lt;/a>
&lt;/div>
&lt;div id="ref-cummingNewStatisticsWhy2014" class="csl-entry">
Cumming, G. (2014). The new statistics: &lt;span>Why&lt;/span> and how. &lt;em>Psychological Science&lt;/em>, &lt;em>25&lt;/em>(1), 7–29. &lt;a href="https://doi.org/10.1177/0956797613504966">https://doi.org/10.1177/0956797613504966&lt;/a>
&lt;/div>
&lt;div id="ref-dijkstraMultilinkComputationalModel2019" class="csl-entry">
Dijkstra, T., Wahl, A., Buytenhuijs, F., Halem, N. V., Al-Jibouri, Z., Korte, M. D., &amp;amp; Rekké, S. (2019). Multilink: &lt;span>A&lt;/span> computational model for bilingual word recognition and word translation. &lt;em>Bilingualism: Language and Cognition&lt;/em>, &lt;em>22&lt;/em>(4), 657–679. &lt;a href="https://doi.org/10.1017/S1366728918000287">https://doi.org/10.1017/S1366728918000287&lt;/a>
&lt;/div>
&lt;div id="ref-kimEffectsLexicalFeatures2018" class="csl-entry">
Kim, M., Crossley, S. A., &amp;amp; Skalicky, S. (2018). Effects of lexical features, textual properties, and individual differences on word processing times during second language reading comprehension. &lt;em>Reading and Writing&lt;/em>, &lt;em>31&lt;/em>(5), 1155–1180. &lt;a href="https://doi.org/10.1007/s11145-018-9833-x">https://doi.org/10.1007/s11145-018-9833-x&lt;/a>
&lt;/div>
&lt;div id="ref-kniefViolatingNormalityAssumption2021" class="csl-entry">
Knief, U., &amp;amp; Forstmeier, W. (2021). Violating the normality assumption may be the lesser of two evils. &lt;em>Behavior Research Methods&lt;/em>. &lt;a href="https://doi.org/10.3758/s13428-021-01587-5">https://doi.org/10.3758/s13428-021-01587-5&lt;/a>
&lt;/div>
&lt;div id="ref-kruschkeBayesianNewStatistics2018" class="csl-entry">
Kruschke, J. K., &amp;amp; Liddell, T. M. (2018). The &lt;span>Bayesian New Statistics&lt;/span>: &lt;span>Hypothesis&lt;/span> testing, estimation, meta-analysis, and power analysis from a &lt;span>Bayesian&lt;/span> perspective. &lt;em>Psychonomic Bulletin &amp;amp; Review&lt;/em>, &lt;em>25&lt;/em>(1), 178–206. &lt;a href="https://doi.org/10.3758/s13423-016-1221-4">https://doi.org/10.3758/s13423-016-1221-4&lt;/a>
&lt;/div>
&lt;div id="ref-leeBayesianCognitiveModeling2014" class="csl-entry">
Lee, M. D., &amp;amp; Wagenmakers, E.-J. (2014). &lt;em>Bayesian cognitive modeling: &lt;span>A&lt;/span> practical course&lt;/em>. &lt;span>Cambridge University Press&lt;/span>. &lt;a href="https://doi.org/10.1017/CBO9781139087759">https://doi.org/10.1017/CBO9781139087759&lt;/a>
&lt;/div>
&lt;div id="ref-lewandowskiGeneratingRandomCorrelation2009" class="csl-entry">
Lewandowski, D., Kurowicka, D., &amp;amp; Joe, H. (2009). Generating random correlation matrices based on vines and extended onion method. &lt;em>Journal of Multivariate Analysis&lt;/em>, &lt;em>100&lt;/em>(9), 1989–2001. &lt;a href="https://doi.org/10.1016/j.jmva.2009.04.008">https://doi.org/10.1016/j.jmva.2009.04.008&lt;/a>
&lt;/div>
&lt;div id="ref-lim2020a" class="csl-entry">
Lim, R. Y., Yap, M. J., &amp;amp; Tse, C.-S. (2020). Individual differences in &lt;span>Cantonese Chinese&lt;/span> word recognition: &lt;span>Insights&lt;/span> from the &lt;span>Chinese Lexicon Project&lt;/span>. &lt;em>Quarterly Journal of Experimental Psychology&lt;/em>, &lt;em>73&lt;/em>(4), 504–518. &lt;a href="https://doi.org/10.1177/1747021820906566">https://doi.org/10.1177/1747021820906566&lt;/a>
&lt;/div>
&lt;div id="ref-loTransformNotTransform2015" class="csl-entry">
Lo, S., &amp;amp; Andrews, S. (2015). To transform or not to transform: Using generalized linear mixed models to analyse reaction time data. &lt;em>Frontiers in Psychology&lt;/em>, &lt;em>6&lt;/em>, 1171. &lt;a href="https://doi.org/10.3389/fpsyg.2015.01171">https://doi.org/10.3389/fpsyg.2015.01171&lt;/a>
&lt;/div>
&lt;div id="ref-matzkePsychologicalInterpretationExGaussian2009" class="csl-entry">
Matzke, D., &amp;amp; Wagenmakers, E.-J. (2009). Psychological interpretation of the ex-&lt;span>Gaussian&lt;/span> and shifted &lt;span>Wald&lt;/span> parameters: &lt;span>A&lt;/span> diffusion model analysis. &lt;em>Psychonomic Bulletin &amp;amp; Review&lt;/em>, &lt;em>16&lt;/em>(5), 798–817. &lt;a href="https://doi.org/10.3758/PBR.16.5.798">https://doi.org/10.3758/PBR.16.5.798&lt;/a>
&lt;/div>
&lt;div id="ref-mendesPervasiveEffectWord2021" class="csl-entry">
Mendes, P. S., &amp;amp; Undorf, M. (2021). On the pervasive effect of word frequency in metamemory. &lt;em>Quarterly Journal of Experimental Psychology&lt;/em>, 17470218211053329. &lt;a href="https://doi.org/10.1177/17470218211053329">https://doi.org/10.1177/17470218211053329&lt;/a>
&lt;/div>
&lt;div id="ref-milekEavesdroppingHappinessRevisited2018" class="csl-entry">
Milek, A., Butler, E. A., Tackman, A. M., Kaplan, D. M., Raison, C. L., Sbarra, D. A., Vazire, S., &amp;amp; Mehl, M. R. (2018). &lt;span>“&lt;span>Eavesdropping&lt;/span> on happiness”&lt;/span> revisited: &lt;span>A&lt;/span> pooled, multisample replication of the association between life satisfaction and observed daily conversation quantity and quality. &lt;em>Psychological Science&lt;/em>, &lt;em>29&lt;/em>(9), 1451–1462. &lt;a href="https://doi.org/10.1177/0956797618774252">https://doi.org/10.1177/0956797618774252&lt;/a>
&lt;/div>
&lt;div id="ref-nicenboimInprep" class="csl-entry">
Nicenboim, B., Schad, D., &amp;amp; Vasishth, S. (n.d.). &lt;em>An introduction to &lt;span>Bayesian&lt;/span> data analysis for cognitive science&lt;/em>. &lt;span>Chapman and Hall/CRC Statistics in the Social and Behavioral Sciences Series&lt;/span>.
&lt;/div>
&lt;div id="ref-pexman2018a" class="csl-entry">
Pexman, P. M., &amp;amp; Yap, M. J. (2018). Individual differences in semantic processing: &lt;span>Insights&lt;/span> from the &lt;span>Calgary&lt;/span> semantic decision project. &lt;em>Journal of Experimental Psychology: Learning, Memory, and Cognition&lt;/em>, &lt;em>44&lt;/em>(7), 1091–1112. &lt;a href="https://doi.org/10.1037/xlm0000499">https://doi.org/10.1037/xlm0000499&lt;/a>
&lt;/div>
&lt;div id="ref-preglaVariabilitySentenceComprehension2021" class="csl-entry">
Pregla, D., Lissón, P., Vasishth, S., Burchert, F., &amp;amp; Stadie, N. (2021). Variability in sentence comprehension in aphasia in &lt;span>German&lt;/span>. &lt;em>Brain and Language&lt;/em>, &lt;em>222&lt;/em>, 105008. &lt;a href="https://doi.org/10.1016/j.bandl.2021.105008">https://doi.org/10.1016/j.bandl.2021.105008&lt;/a>
&lt;/div>
&lt;div id="ref-rodriguez-ferreiroSemanticPrimingSchizotypal2020" class="csl-entry">
Rodríguez-Ferreiro, J., Aguilera, M., &amp;amp; Davies, R. (2020). Semantic priming and schizotypal personality: Reassessing the link between thought disorder and enhanced spreading of semantic activation. &lt;em>PeerJ&lt;/em>, &lt;em>8&lt;/em>, e9511. &lt;a href="https://doi.org/10.7717/peerj.9511">https://doi.org/10.7717/peerj.9511&lt;/a>
&lt;/div>
&lt;div id="ref-rouderBayesianInferencePsychology2018" class="csl-entry">
Rouder, J. N., Haaf, J. M., &amp;amp; Vandekerckhove, J. (2018). Bayesian inference for psychology, part &lt;span>IV&lt;/span>: &lt;span>Parameter&lt;/span> estimation and &lt;span>Bayes&lt;/span> factors. &lt;em>Psychonomic Bulletin &amp;amp; Review&lt;/em>, &lt;em>25&lt;/em>(1), 102–113. &lt;a href="https://doi.org/10.3758/s13423-017-1420-7">https://doi.org/10.3758/s13423-017-1420-7&lt;/a>
&lt;/div>
&lt;div id="ref-schielzethRobustnessLinearMixed2020" class="csl-entry">
Schielzeth, H., Dingemanse, N. J., Nakagawa, S., Westneat, D. F., Allegue, H., Teplitsky, C., Réale, D., Dochtermann, N. A., Garamszegi, L. Z., &amp;amp; Araya‐Ajoy, Y. G. (2020). Robustness of linear mixed‐effects models to violations of distributional assumptions. &lt;em>Methods in Ecology and Evolution&lt;/em>, &lt;em>11&lt;/em>(9), 1141–1152. &lt;a href="https://doi.org/10.1111/2041-210X.13434">https://doi.org/10.1111/2041-210X.13434&lt;/a>
&lt;/div>
&lt;div id="ref-schmalzWhatBayesFactor2021" class="csl-entry">
Schmalz, X., Biurrun Manresa, J., &amp;amp; Zhang, L. (2021). What is a &lt;span>Bayes&lt;/span> factor? &lt;em>Psychological Methods&lt;/em>. &lt;a href="https://doi.org/10.1037/met0000421">https://doi.org/10.1037/met0000421&lt;/a>
&lt;/div>
&lt;div id="ref-stoneEffectDecayLexical2020" class="csl-entry">
Stone, K., Malsburg, T. von der, &amp;amp; Vasishth, S. (2020). The effect of decay and lexical uncertainty on processing long-distance dependencies in reading. &lt;em>PeerJ&lt;/em>, &lt;em>8&lt;/em>, e10438. &lt;a href="https://doi.org/10.7717/peerj.10438">https://doi.org/10.7717/peerj.10438&lt;/a>
&lt;/div>
&lt;div id="ref-stoneInteractionGrammaticallyDistinct2021" class="csl-entry">
Stone, K., Veríssimo, J., Schad, D. J., Oltrogge, E., Vasishth, S., &amp;amp; Lago, S. (2021). The interaction of grammatically distinct agreement dependencies in predictive processing. &lt;em>Language, Cognition and Neuroscience&lt;/em>, &lt;em>36&lt;/em>(9), 1159–1179. &lt;a href="https://doi.org/10.1080/23273798.2021.1921816">https://doi.org/10.1080/23273798.2021.1921816&lt;/a>
&lt;/div>
&lt;div id="ref-tendeiroReviewIssuesNull2019" class="csl-entry">
Tendeiro, J. N., &amp;amp; Kiers, H. A. L. (2019). A review of issues about null hypothesis &lt;span>Bayesian&lt;/span> testing. &lt;em>Psychological Methods&lt;/em>, &lt;em>24&lt;/em>(6), 774–795. &lt;a href="https://doi.org/10.1037/met0000221">https://doi.org/10.1037/met0000221&lt;/a>
&lt;/div>
&lt;div id="ref-tendeiroOnTheWhite2022" class="csl-entry">
Tendeiro, J. N., &amp;amp; Kiers, H. A. L. (in press). On the white, the black, and the many shades of gray in between: &lt;span>Our&lt;/span> reply to van &lt;span>Ravenzwaaij&lt;/span> and &lt;span>Wagenmakers&lt;/span> (2021). &lt;em>Psychological Methods&lt;/em>.
&lt;/div>
&lt;div id="ref-schootBayesianStatisticsModelling2021" class="csl-entry">
Van de Schoot, R., Depaoli, S., Gelman, A., King, R., Kramer, B., Märtens, K., Tadesse, M. G., Vannucci, M., Willemsen, J., &amp;amp; Yau, C. (2021). Bayesian statistics and modelling. &lt;em>Nature Reviews Methods Primers&lt;/em>, &lt;em>1&lt;/em>, 3. &lt;a href="https://doi.org/10.1038/s43586-020-00003-0">https://doi.org/10.1038/s43586-020-00003-0&lt;/a>
&lt;/div>
&lt;div id="ref-vanravenzwaaijAdvantagesMasqueradingIssues2021" class="csl-entry">
van Ravenzwaaij, D., &amp;amp; Wagenmakers, E.-J. (2021). Advantages masquerading as &lt;span>“issues”&lt;/span> in &lt;span>Bayesian&lt;/span> hypothesis testing: &lt;span>A&lt;/span> commentary on &lt;span>Tendeiro&lt;/span> and &lt;span>Kiers&lt;/span> (2019). &lt;em>Psychological Methods&lt;/em>. &lt;a href="https://doi.org/10.1037/met0000415">https://doi.org/10.1037/met0000415&lt;/a>
&lt;/div>
&lt;div id="ref-vasishthBayesianDataAnalysis2018" class="csl-entry">
Vasishth, S., Nicenboim, B., Beckman, M. E., Li, F., &amp;amp; Kong, E. J. (2018). Bayesian data analysis in the phonetic sciences: &lt;span>A&lt;/span> tutorial introduction. &lt;em>Journal of Phonetics&lt;/em>, &lt;em>71&lt;/em>, 147–161. &lt;a href="https://doi.org/10.1016/j.wocn.2018.07.008">https://doi.org/10.1016/j.wocn.2018.07.008&lt;/a>
&lt;/div>
&lt;div id="ref-yarkoniMovingColtheartNew2008" class="csl-entry">
Yarkoni, T., Balota, D., &amp;amp; Yap, M. J. (2008). Moving beyond &lt;span>Coltheart&lt;/span>’s &lt;span>N&lt;/span>: &lt;span>A&lt;/span> new measure of orthographic similarity. &lt;em>Psychonomic Bulletin &amp;amp; Review&lt;/em>, &lt;em>15&lt;/em>(5), 971–979. &lt;a href="https://doi.org/10.3758/PBR.15.5.971">https://doi.org/10.3758/PBR.15.5.971&lt;/a>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div></description><category>Bayesian statistics</category><category>linear mixed-effects models</category><category>priors</category><category>predictive checks</category><category>sensitivity analysis</category><category>R</category><category>visualisation</category><category>brms</category><category>s</category><category>R</category><category>statistics</category></item><item><title>Avoiding (R) Markdown knitting errors using knit_deleting_service_files()</title><link>https://pablobernabeu.github.io/2021/avoiding-knitting-errors-in-r-markdown-using-knit-deleting-service-files/</link><pubDate>Fri, 17 Dec 2021 21:46:06 +0000</pubDate><guid>https://pablobernabeu.github.io/2021/avoiding-knitting-errors-in-r-markdown-using-knit-deleting-service-files/</guid><description>
&lt;p>The function &lt;a href="https://github.com/pablobernabeu/knit_deleting_service_files/blob/main/knit_deleting_service_files.R">&lt;code>knit_deleting_service_files()&lt;/code>&lt;/a> helps avoid (R) Markdown &lt;a href="https://pablobernabeu.github.io/2021/tackling-knitting-errors-in-r-markdown/">knitting errors&lt;/a> caused by files and folders remaining from previous knittings (e.g., manuscript.tex, ZHJhZnQtYXBhLlJtZA==.Rmd, manuscript.synctex.gz). The only obligatory argument for this function is the name of a .Rmd or .md file. The optional argument is a path to a directory containing this file.&lt;/p>
&lt;p>The function first offers deleting potential service files and folders, for which the user’s approval is requested in the console (see screenshot below). Next, the document is knitted. Last, the function offers deleting potential service files and folders again.&lt;/p>
&lt;p>NOTE: The deletions, if accepted, are irreversible as they are made through &lt;a href="https://stat.ethz.ch/R-manual/R-devel/library/base/html/unlink.html">&lt;code>unlink()&lt;/code>&lt;/a>. Therefore, our familiar adage truly applies: this function comes with ABSOLUTELY NO WARRANTY. Please ensure you understand the &lt;a href="https://github.com/pablobernabeu/knit_deleting_service_files/blob/main/knit_deleting_service_files.R">source code&lt;/a> before using the function.&lt;/p>
&lt;p>&lt;img src='images/Screenshot%202021-12-18%20at%2020.27.49.png' alt='Screenshot of the function in use' style='margin-top:2px; margin-bottom:-2px;'>&lt;/img>&lt;/p>
&lt;p>&lt;span style="font-size:90%; color: #899499;">Screenshot of the function in use.&lt;/span>&lt;/p>
&lt;div id="the-function" class="section level2">
&lt;h2>The function&lt;/h2>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2Fknit_deleting_service_files%2Fblob%2Fmain%2Fknit_deleting_service_files.R&amp;style=a11y-dark&amp;type=code&amp;showBorder=on&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showFullPath=on&amp;showCopy=on">&lt;/script>
&lt;/div></description><category>s</category><category>R Markdown</category><category>papaja</category><category>render</category><category>R</category></item><item><title>Walking the line between reproducibility and efficiency in R Markdown: Three methods</title><link>https://pablobernabeu.github.io/2021/walking-the-line-between-reproducibility-and-efficiency-in-r-markdown-three-methods/</link><pubDate>Sun, 14 Nov 2021 00:10:08 +0000</pubDate><guid>https://pablobernabeu.github.io/2021/walking-the-line-between-reproducibility-and-efficiency-in-r-markdown-three-methods/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2021/walking-the-line-between-reproducibility-and-efficiency-in-r-markdown-three-methods/index.en_files/header-attrs/header-attrs.js">&lt;/script>
&lt;p>As technology and research methods advance, the data sets tend to be larger and the methods more exhaustive. Consequently, the analyses take longer to run. This poses a challenge when the results are to be presented using &lt;a href="https://rmarkdown.rstudio.com/index.html">R Markdown&lt;/a>. One has to balance reproducibility and efficiency. On the one hand, it is desirable to keep the R Markdown document as self-contained as possible, so that those who may later examine the document can easily test and edit the code. On the other hand, it would be inefficient to create a document that is very slow to run or very long. The context of the task will determine how how time-consuming and long the code in an Rmd file can be. For instance, one could decide that the knitting can take up to 15 minutes, and each code chunk can span up to 30 lines.&lt;/p>
&lt;p>Several methods can be used in each document to accommodate different types of code. Three methods are presented below, ordered from easier-to-reproduce to easier-to-knit.&lt;/p>
&lt;ol style="list-style-type: decimal">
&lt;li>&lt;p>For &lt;strong>fast- and concise-enough code:&lt;/strong> Provide the original code in the Rmd file. The code is run as the document is knitted. Example:&lt;/p>
&lt;pre>&lt;code> nrow(myData)&lt;/code>&lt;/pre>&lt;/li>
&lt;li>&lt;p>For &lt;strong>fast-enough but very long code:&lt;/strong> Store the code in a separate script and &lt;code>source&lt;/code> it in the Rmd file. The code is run as the document is knitted. Example:&lt;/p>
&lt;pre>&lt;code> source(&amp;#39;analysis/model_diagnostics.R&amp;#39;)&lt;/code>&lt;/pre>&lt;/li>
&lt;li>&lt;p>For &lt;strong>very slow and/or long code:&lt;/strong> Store the code in a separate script and run it prior to knitting the Rmd file, so that the output from the code (e.g., a model, a plot) is saved and can be read into the Rmd. Example:&lt;/p>
&lt;pre>&lt;code> model_1 = readRDS(&amp;#39;results/model_1.rds&amp;#39;)&lt;/code>&lt;/pre>&lt;/li>
&lt;/ol>
&lt;p>Importantly, even the third method allows the reproducibility of the code. It just requires a bit of additional documentation to ensure that the end user can also access the script in which the result was produced (e.g., ‘analysis/model_1.R’).&lt;/p></description><category>s</category><category>R</category><category>R Markdown</category><category>R</category></item><item><title>Tackling knitting errors in R Markdown</title><link>https://pablobernabeu.github.io/2021/tackling-knitting-errors-in-r-markdown/</link><pubDate>Sat, 13 Nov 2021 18:11:22 +0000</pubDate><guid>https://pablobernabeu.github.io/2021/tackling-knitting-errors-in-r-markdown/</guid><description>
&lt;script src="https://pablobernabeu.github.io/2021/tackling-knitting-errors-in-r-markdown/index.en_files/header-attrs/header-attrs.js">&lt;/script>
&lt;p>When knitting an R Markdown document after the first time, errors may sometimes appear. Three tips are recommended below.&lt;/p>
&lt;div id="close-pdf-reader-window" class="section level2">
&lt;h2>1. Close PDF reader window&lt;/h2>
&lt;p>When the document is knitted through the ‘Knit’ button, a PDF reader window opens to present the result. Closing this window can help resolve errors.&lt;/p>
&lt;/div>
&lt;div id="delete-service-files" class="section level2">
&lt;h2>2. Delete service files&lt;/h2>
&lt;p>Every time the Rmd is knitted, some service files are created. Some of these files have the ‘.tex’ extension (e.g., index.tex, Appendix-B.tex), whereas others do not (e.g., index.log, ZHJhZnQtYXBhLlJtZA==.Rmd, index.synctex.gz). Deleting these files can help resolve errors (see a &lt;a href="https://pablobernabeu.github.io/2021/avoiding-knitting-errors-in-r-markdown-using-knit-deleting-service-files/">possible function&lt;/a>).&lt;/p>
&lt;/div>
&lt;div id="delete-code-chunks-related-to-the-appendices" class="section level2">
&lt;h2>3. Delete code chunks related to the appendices&lt;/h2>
&lt;p>When knitting &lt;a href="https://github.com/crsh/papaja">papaja&lt;/a> documents containing any appendices, some code chunks related to the appendices will automatically appear at the end of the primary Rmd file—e.g.:&lt;/p>
&lt;pre>&lt;code>```{r echo = FALSE, results = &amp;#39;asis&amp;#39;, cache = FALSE}
papaja::render_appendix(&amp;#39;Appendix-A.Rmd&amp;#39;)
```&lt;/code>&lt;/pre>
&lt;p>Normally, these code chunks are automatically removed as the knitting finishes. However, if the chunks remain in place, deleting them manually can help resolve errors.&lt;/p>
&lt;/div></description><category>s</category><category>R</category><category>R Markdown</category><category>R</category></item><item><title>Parallelizing simr::powercurve() in R</title><link>https://pablobernabeu.github.io/2021/parallelizing-simr-powercurve/</link><pubDate>Fri, 23 Jul 2021 16:46:54 +0100</pubDate><guid>https://pablobernabeu.github.io/2021/parallelizing-simr-powercurve/</guid><description>
&lt;p>The &lt;code>powercurve&lt;/code> function from the R package &lt;a href="https://cran.r-project.org/web/packages/simr/simr.pdf">‘simr’&lt;/a> (Green &amp;amp; MacLeod, 2016) can incur very long running times when the method used for the calculation of &lt;em>p&lt;/em> values is Kenward-Roger or Satterthwaite (see Luke, 2017). Here I suggest three ways for cutting down this time.&lt;/p>
&lt;ol style="list-style-type: decimal">
&lt;li>&lt;p>Where possible, use a high-performance (or high-end) computing cluster. This removes the need to use personal computers for these long jobs.&lt;/p>&lt;/li>
&lt;li>&lt;p>In case you’re using the &lt;code>fixed()&lt;/code> parameter of the &lt;code>powercurve&lt;/code> function, and calculating the power for different effects, run these at the same time (‘in parallel’) on different machines, rather than one after another.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;em>Parallelize&lt;/em> the &lt;code>breaks&lt;/code> argument. The &lt;code>breaks&lt;/code> argument of the &lt;code>powercurve&lt;/code> function allows the calculation of power for different levels of the grouping factor passed to &lt;code>along&lt;/code>. Some grouping factors are &lt;em>participant&lt;/em>, &lt;em>trial&lt;/em> and &lt;em>item&lt;/em>. The &lt;code>breaks&lt;/code> argument sets the different sample sizes for which power will be calculated. Parallelizing &lt;code>breaks&lt;/code> is done by running each number of levels in a separate function. When each has been run and saved, they are &lt;code>c&lt;/code>ombined to allow the plotting. This procedure is demonstrated below.&lt;/p>&lt;/li>
&lt;/ol>
&lt;div id="parallelizing-breaks" class="section level2">
&lt;h2>Parallelizing &lt;code>breaks&lt;/code>&lt;/h2>
&lt;p>Let’s do a minimal example using a toy &lt;code>lmer&lt;/code> model. A power curve will be created for the fixed effect of &lt;code>x&lt;/code> along different sample sizes of the grouping factor &lt;code>g&lt;/code>.&lt;/p>
&lt;p>Notice that the six sections of the power curve below are serially arranged, one after another. In contrast, to enable parallel processing, each power curve would be placed in a single script, and they would all be run at the same time.&lt;/p>
&lt;p>Although the power curves below run in a few minutes, the settings that are often used (e.g., a larger model; &lt;code>fixed('x', 'sa')&lt;/code> instead of &lt;code>fixed('x')&lt;/code>; &lt;code>nsim = 500&lt;/code> instead of &lt;code>nsim = 50&lt;/code>) take far longer. That is where parallel processing becomes useful.&lt;a href="#fn1" class="footnote-ref" id="fnref1">&lt;sup>1&lt;/sup>&lt;/a>&lt;/p>
&lt;pre class="r">&lt;code>library(lme4)
library(simr)
# Toy model with data from &amp;#39;simr&amp;#39; package
fm = lmer(y ~ x + (x | g), data = simdata)
# Extend sample size of `g`
fm_extended_g = extend(fm, along = &amp;#39;g&amp;#39;, n = 12)
# Parallelize `breaks` by running each number of levels in a separate function.
# 4 levels of g
pwcurve_4g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 4,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 6 levels of g
pwcurve_6g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 6,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 8 levels of g
pwcurve_8g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 8,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 10 levels of g
pwcurve_10g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 10,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 12 levels of g
pwcurve_12g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 12,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)&lt;/code>&lt;/pre>
&lt;p>Having saved each section of the power curve, we must now combine them to be able to plot them together (if you wish to automatise this procedure, consider &lt;a href="https://github.com/pablobernabeu/Language-and-vision-in-conceptual-processing-Multilevel-analysis-and-statistical-power/blob/main/R_functions/combine_powercurve_chunks.R">this function&lt;/a>).&lt;/p>
&lt;pre class="r">&lt;code># Create a destination object using any of the power curves above.
all_pwcurve = pwcurve_4g
# Combine results
all_pwcurve$ps = c(pwcurve_4g$ps[1], pwcurve_6g$ps[1], pwcurve_8g$ps[1],
pwcurve_10g$ps[1], pwcurve_12g$ps[1])
# Combine the different numbers of levels.
all_pwcurve$xval = c(pwcurve_4g$nlevels, pwcurve_6g$nlevels, pwcurve_8g$nlevels,
pwcurve_10g$nlevels, pwcurve_12g$nlevels)
print(all_pwcurve)&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## Power for predictor &amp;#39;x&amp;#39;, (95% confidence interval),
## by number of levels in g:
## 4: 46.00% (31.81, 60.68) - 40 rows
## 6: 74.00% (59.66, 85.37) - 60 rows
## 8: 92.00% (80.77, 97.78) - 80 rows
## 10: 98.00% (89.35, 99.95) - 100 rows
## 12: 100.0% (92.89, 100.0) - 120 rows
##
## Time elapsed: 0 h 0 m 7 s&lt;/code>&lt;/pre>
&lt;pre class="r">&lt;code>plot(all_pwcurve, xlab = &amp;#39;Levels of g&amp;#39;)&lt;/code>&lt;/pre>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2021/parallelizing-simr-powercurve/index_files/figure-html/unnamed-chunk-2-1.png" width="672" alt="Power curve for effect of x rising with levels of grouping factor g, crossing the 80% threshold near 7 levels." />&lt;/p>
&lt;pre class="r">&lt;code># For reproducibility purposes
sessionInfo()&lt;/code>&lt;/pre>
&lt;pre>&lt;code>## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_United Kingdom.utf8
## [2] LC_CTYPE=English_United Kingdom.utf8
## [3] LC_MONETARY=English_United Kingdom.utf8
## [4] LC_NUMERIC=C
## [5] LC_TIME=English_United Kingdom.utf8
##
## time zone: Europe/London
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices datasets utils methods base
##
## other attached packages:
## [1] simr_1.0.7 lme4_1.1-37 Matrix_1.7-3
## [4] knitr_1.50 xaringanExtra_0.8.0
##
## loaded via a namespace (and not attached):
## [1] tidyr_1.3.1 sass_0.4.10 generics_0.1.4 renv_1.1.5
## [5] stringi_1.8.7 blogdown_1.21 lattice_0.22-7 digest_0.6.37
## [9] magrittr_2.0.3 evaluate_1.0.4 grid_4.5.1 bookdown_0.43
## [13] iterators_1.0.14 fastmap_1.2.0 plyr_1.8.9 jsonlite_2.0.0
## [17] backports_1.5.0 Formula_1.2-5 mgcv_1.9-3 purrr_1.1.0
## [21] jquerylib_0.1.4 abind_1.4-8 reformulas_0.4.1 Rdpack_2.6.4
## [25] cli_3.6.5 rlang_1.1.6 rbibutils_2.3 binom_1.1-1.1
## [29] splines_4.5.1 plotrix_3.8-4 cachem_1.1.0 yaml_2.3.10
## [33] RLRsim_3.1-8 parallel_4.5.1 tools_4.5.1 pbkrtest_0.5.5
## [37] uuid_1.2-1 nloptr_2.2.1 minqa_1.2.8 dplyr_1.1.4
## [41] boot_1.3-31 broom_1.0.9 vctrs_0.6.5 R6_2.6.1
## [45] lifecycle_1.0.4 stringr_1.5.1 car_3.1-3 MASS_7.3-65
## [49] pkgconfig_2.0.3 bslib_0.9.0 pillar_1.11.0 glue_1.8.0
## [53] Rcpp_1.1.0 tidyselect_1.2.1 tibble_3.3.0 xfun_0.52
## [57] htmltools_0.5.8.1 nlme_3.1-168 rmarkdown_2.29 carData_3.0-5
## [61] compiler_4.5.1&lt;/code>&lt;/pre>
&lt;div id="just-the-code" class="section level3">
&lt;h3>Just the code&lt;/h3>
&lt;pre>&lt;code>
library(lme4)
library(simr)
# Toy model
fm = lmer(y ~ x + (x | g), data = simdata)
# Extend sample size of `g`
fm_extended_g = extend(fm, along = &amp;#39;g&amp;#39;, n = 12)
# Parallelize `breaks` by running each number of levels in a separate function.
# 4 levels of g
pwcurve_4g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 4,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 6 levels of g
pwcurve_6g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 6,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 8 levels of g
pwcurve_8g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 8,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 10 levels of g
pwcurve_10g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 10,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# 12 levels of g
pwcurve_12g = powerCurve(fm_extended_g, fixed(&amp;#39;x&amp;#39;), along = &amp;#39;g&amp;#39;, breaks = 12,
nsim = 50, seed = 123,
# No progress bar
progress = FALSE)
# Create a destination object using any of the power curves above.
all_pwcurve = pwcurve_4g
# Combine results
all_pwcurve$ps = c(pwcurve_4g$ps[1], pwcurve_6g$ps[1], pwcurve_8g$ps[1],
pwcurve_10g$ps[1], pwcurve_12g$ps[1])
# Combine the different numbers of levels.
all_pwcurve$xval = c(pwcurve_4g$nlevels, pwcurve_6g$nlevels, pwcurve_8g$nlevels,
pwcurve_10g$nlevels, pwcurve_12g$nlevels)
print(all_pwcurve)
plot(all_pwcurve, xlab = &amp;#39;Levels of g&amp;#39;)
&lt;/code>&lt;/pre>
&lt;/div>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Brysbaert, M., &amp;amp; Stevens, M. (2018). Power analysis and effect size in mixed effects models: A tutorial. &lt;em>Journal of Cognition, 1&lt;/em>(1), 9. &lt;a href="http://doi.org/10.5334/joc.10" class="uri">http://doi.org/10.5334/joc.10&lt;/a>&lt;/p>
&lt;p>Green, P., &amp;amp; MacLeod, C. J. (2016). SIMR: An R package for power analysis of generalized linear mixed models by simulation. &lt;em>Methods in Ecology and Evolution 7&lt;/em>(4), 493–498, &lt;a href="https://doi.org/10.1111/2041-210X.12504" class="uri">https://doi.org/10.1111/2041-210X.12504&lt;/a>&lt;/p>
&lt;p>Kumle, L., Vo, M. L. H., &amp;amp; Draschkow, D. (2021). Estimating power in (generalized) linear mixed models: An open introduction and tutorial in R. &lt;em>Behavior Research Methods&lt;/em>, 1–16. &lt;a href="https://doi.org/10.3758/s13428-021-01546-0" class="uri">https://doi.org/10.3758/s13428-021-01546-0&lt;/a>&lt;/p>
&lt;p>Luke, S. G. (2017). Evaluating significance in linear mixed-effects models in R. &lt;em>Behavior Research Methods, 49&lt;/em>(4), 1494–1502. &lt;a href="https://doi.org/10.3758/s13428-016-0809-y" class="uri">https://doi.org/10.3758/s13428-016-0809-y&lt;/a>&lt;/p>
&lt;/div>
&lt;div class="footnotes footnotes-end-of-document">
&lt;hr />
&lt;ol>
&lt;li id="fn1">&lt;p>The number of simulations set by &lt;code>nsim&lt;/code> should be larger (Brysbaert &amp;amp; Stevens, 2018; Green &amp;amp; MacLeod, 2016). In addition, the effect size for &lt;code>x&lt;/code> should be adjusted to the value that best fits with the planned study (Kumle et al., 2021).&lt;a href="#fnref1" class="footnote-back">↩︎&lt;/a>&lt;/p>&lt;/li>
&lt;/ol>
&lt;/div></description><category>s</category><category>power analysis</category><category>R</category><category>research methods</category></item><item><title>WebVTT caption transcription app</title><link>https://pablobernabeu.github.io/applications-and-dashboards/vtt-transcription-app/</link><pubDate>Fri, 01 Jan 2021 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/applications-and-dashboards/vtt-transcription-app/</guid><description>
&lt;div id="how-it-works" class="section level3">
&lt;h3>How it works&lt;/h3>
&lt;div class="mermaid">
graph TD
A["User uploads WebVTT file&lt;br/>(vtt or txt)"] --> B["Regular expressions remove&lt;br/>metadata such as timestamps"]
B --> C["Text formatted&lt;br/>into a paragraph"]
C --> D["Result displayed&lt;br/>on the website"]
D --> E["Download as docx&lt;br/>or txt document"]
&lt;/div>
&lt;p>This open-source, R-based web application converts video captions (subtitles) from the &lt;a href="https://www.w3.org/TR/webvtt1/">Web Video Text Tracks (WebVTT) Format&lt;/a> into plain text. For this purpose, users upload a WebVTT file with the extension &lt;code>.vtt&lt;/code> or &lt;code>.txt&lt;/code> (examples available &lt;a href="https://github.com/pablobernabeu/VTT-Transcription-App/blob/main/assets/Example_subtitles_1.vtt">here&lt;/a> and &lt;a href="https://github.com/pablobernabeu/VTT-Transcription-App/blob/main/assets/Example_subtitles_2.txt">here&lt;/a>).&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FVTT-Transcription-App%2Fblob%2Fmain%2Fassets%2FExample_subtitles_1.vtt&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>&lt;a href="https://osf.io/download/ustmx">&lt;strong>Download VTT file&lt;/strong>&lt;/a>&lt;/p>
&lt;p>When the caption file is uploaded to the web application, metadata such as timestamps are automatically removed, and the text is formatted into a paragraph. The result is displayed on the website, and can be downloaded as &lt;code>.docx&lt;/code> and &lt;code>.txt&lt;/code> documents. Overall, this application serves to improve the accessibility of video captions.&lt;/p>
&lt;p>The data is only available to the user, and is deleted when the website is closed.&lt;/p>
&lt;/div>
&lt;div id="web-application" class="section level2">
&lt;h2>&lt;i class="fa-solid fa-globe">&lt;/i>&amp;nbsp;Web application&lt;/h2>
&lt;p>The application can be used below, or it can be &lt;a href="https://pablo-bernabeu.shinyapps.io/VTT-Transcription-App">opened separately here&lt;/a>.&lt;/p>
&lt;div style="margin-bottom: 25px;">
&lt;div style="position: relative; padding-top: 56.25%; height: 1100px;">
&lt;iframe src="https://pablo-bernabeu.shinyapps.io/VTT-Transcription-App" frameborder="0" allowfullscreen style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
&lt;/iframe>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="programming-details" class="section level2">
&lt;h2>Programming details&lt;/h2>
&lt;p>The &lt;a href="https://github.com/pablobernabeu/VTT-transcription">source code is available on Github&lt;/a>, where the app can be extended via pull requests. Questions and suggestions can be submitted as &lt;a href="https://github.com/pablobernabeu/VTT-transcription/issues">issues&lt;/a> or emailed to &lt;a href="mailto:pcbernabeu@gmail.com" class="email">pcbernabeu@gmail.com&lt;/a>. The licence is &lt;a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International&lt;/a>.&lt;/p>
&lt;p>The core of the application is in the &lt;a href="https://github.com/pablobernabeu/VTT-Transcription-App/blob/main/index.Rmd">index.Rmd&lt;/a> script, which uses ‘&lt;a href="https://stringr.tidyverse.org/articles/regular-expressions.html">regular expressions&lt;/a>’ to process the VTT file.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FVTT-Transcription-App%2Fblob%2Fmain%2Findex.Rmd%23L172-L188&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;p>In turn, the script above draws on &lt;a href="https://github.com/pablobernabeu/VTT-Transcription-App/blob/main/assets/VTT-Transcription-App_doc_renderer.Rmd">the one below&lt;/a> to enable the download of &lt;code>.docx&lt;/code> documents. Last, the latter script draws on &lt;a href="https://github.com/pablobernabeu/VTT-Transcription-App/blob/main/assets/VTT-Transcription-App-format-template.docx">this Word template&lt;/a>.&lt;/p>
&lt;script src="https://emgithub.com/embed-v2.js?target=https%3A%2F%2Fgithub.com%2Fpablobernabeu%2FVTT-Transcription-App%2Fblob%2Fmain%2Fassets%2FVTT-Transcription-App_doc_renderer.Rmd%23L1-L13&amp;style=a11y-dark&amp;type=code&amp;showLineNumbers=on&amp;showFileMeta=on&amp;showCopy=on&amp;fetchFromJsDelivr=on">&lt;/script>
&lt;/div></description><category>subtitles</category><category>accessibility</category><category>transcription</category><category>webvtt</category><category>web video text tracks format</category><category>web application</category><category>data science</category><category>regular expressions</category><category>stringr</category><category>R</category><category>R Shiny</category><category>Flexdashboard</category><category>software</category><category>research and teaching applications</category><category>web application</category><category>R</category></item><item><title>R Markdown amidst Madison parks</title><link>https://pablobernabeu.github.io/2020/r-markdown-amidst-madison-parks/</link><pubDate>Fri, 14 Aug 2020 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2020/r-markdown-amidst-madison-parks/</guid><description>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/header-attrs/header-attrs.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/htmlwidgets/htmlwidgets.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/plotly-binding/plotly.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/typedarray/typedarray.min.js">&lt;/script>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/jquery/jquery.min.js">&lt;/script>
&lt;link href="https://pablobernabeu.github.io/rmarkdown-libs/crosstalk/css/crosstalk.min.css" rel="stylesheet" />
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/crosstalk/js/crosstalk.min.js">&lt;/script>
&lt;link
href="https://pablobernabeu.github.io/rmarkdown-libs/plotly-htmlwidgets-css/plotly-htmlwidgets.css"
rel="stylesheet"
/>
&lt;script src="https://pablobernabeu.github.io/rmarkdown-libs/plotly-main/plotly-latest.min.js">&lt;/script>
&lt;p>
This document is part of teaching materials created for the workshop
&lt;a
href="https://github.com/pablobernabeu/CarpentryCon-2020-workshop-Open-Data-Reproducibility"
target="_top"
>‘Open data and reproducibility v2.1: R Markdown, dashboards and Binder’&lt;/a
>, delivered at the
&lt;a href="https://2020.carpentrycon.org/">CarpentryCon 2020 conference&lt;/a>. The
purpose of this specific document is to practise R Markdown, including basic
features such as Markdown markup and code chunks, along with more special
features such as
&lt;a href="https://bookdown.org/yihui/rmarkdown-cookbook/cross-ref.html"
>cross-references for figures, tables, code chunks, etc&lt;/a
>. The code is
&lt;a
href="https://github.com/pablobernabeu/Data-is-present/blob/master/examples-documents-dashboards/R%20Markdown/R-Markdown-amidst-Madison-parks.Rmd"
>on GitHub&lt;/a
>.
&lt;/p>
&lt;p>
Since this conference was originally going to take place in Madison, let’s
look at some
&lt;a
href="https://data-cityofmadison.opendata.arcgis.com/datasets/parks?geometry=-89.997%2C43.007%2C-88.679%2C43.183"
>open data from the City of Madison&lt;/a
>.
&lt;/p>
&lt;div id="park-types" class="section level2">
&lt;h2>Park types&lt;/h2>
&lt;p>
&lt;font style="color: grey"
>[Placeholder text] Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.&lt;/font
>
Figure &lt;a href="#fig:park-types">1&lt;/a> shows the number of parks within each
type.
&lt;/p>
&lt;pre class="r">&lt;code># Showing the code because echo = TRUE
dat = read.csv(&amp;#39;https://opendata.arcgis.com/datasets/9e00ff81868e49b7ba65d4e628b9e14f_6.csv&amp;#39;)
dat =
dat %&amp;gt;%
group_by(Type) %&amp;gt;%
mutate(parks_number = n())
ggplotly(
ggplot(dat, aes(x=reorder(Type, parks_number), y=parks_number,
text = paste(&amp;#39;Number of parks =&amp;#39;, parks_number))) +
theme(axis.title.y=element_blank()) + stat_identity(geom=&amp;#39;bar&amp;#39;) +
labs(x=&amp;#39;Type&amp;#39;, y=&amp;#39;Number of parks&amp;#39;) + coord_flip(),
tooltip = &amp;#39;text&amp;#39;
)&lt;/code>&lt;/pre>
&lt;div class="figure">
&lt;span style="display: block" id="fig:park-types">&lt;/span>
&lt;div
id="htmlwidget-1"
style="width: 672px; height: 480px"
class="plotly html-widget"
>&lt;/div>
&lt;script type="application/json" data-for="htmlwidget-1">
{
"x": {
"data": [
{
"orientation": "h",
"width": [
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.9, 0.899999999999999, 0.899999999999999, 0.899999999999999,
0.9, 0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.899999999999999, 0.9, 0.899999999999999, 0.9, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.9, 0.899999999999999, 0.899999999999999, 0.899999999999999,
0.9, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.9, 0.899999999999999, 0.9, 0.899999999999999, 0.9,
0.899999999999999, 0.9, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.9, 0.9, 0.899999999999999, 0.9, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.9, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.9, 0.899999999999999, 0.9,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.9, 0.899999999999999, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.9, 0.899999999999999, 0.899999999999999, 0.899999999999999,
0.9, 0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999, 0.9,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.9, 0.899999999999999, 0.9, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.9, 0.9, 0.9, 0.9,
0.899999999999999, 0.9, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.9, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.9, 0.899999999999999, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.9, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.9,
0.899999999999999, 0.899999999999999, 0.9, 0.9,
0.899999999999999, 0.899999999999999, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.899999999999999,
0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.899999999999999,
0.899999999999999, 0.899999999999999, 0.9, 0.9, 0.9, 0.9,
0.899999999999999, 0.899999999999999
],
"base": [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
],
"x": [
100, 100, 22, 78, 78, 21, 31, 100, 78, 100, 78, 31, 100, 78,
100, 78, 78, 100, 21, 31, 100, 78, 100, 2, 100, 100, 100, 100,
78, 100, 100, 100, 78, 100, 100, 21, 2, 78, 78, 100, 21, 100,
31, 100, 22, 1, 78, 100, 78, 78, 78, 100, 100, 13, 78, 100, 78,
100, 22, 100, 78, 100, 31, 78, 100, 100, 78, 31, 100, 100, 100,
78, 100, 100, 78, 21, 100, 21, 100, 78, 100, 21, 21, 100, 100,
100, 1, 31, 100, 78, 100, 78, 78, 13, 21, 78, 22, 100, 22, 100,
31, 31, 31, 78, 100, 31, 31, 100, 22, 31, 78, 100, 78, 100, 100,
100, 78, 100, 100, 31, 21, 22, 78, 78, 78, 22, 13, 100, 31, 100,
78, 31, 78, 21, 100, 21, 31, 78, 100, 78, 31, 100, 78, 78, 22,
78, 21, 100, 100, 100, 31, 78, 100, 78, 100, 22, 22, 78, 100,
78, 78, 13, 78, 100, 31, 78, 100, 78, 31, 100, 13, 100, 22, 13,
13, 78, 78, 100, 78, 78, 78, 100, 100, 22, 78, 21, 13, 21, 22,
78, 21, 13, 22, 100, 78, 31, 31, 13, 78, 78, 100, 100, 100, 78,
100, 100, 100, 21, 100, 31, 100, 31, 22, 100, 78, 22, 100, 100,
100, 78, 31, 100, 78, 31, 78, 100, 78, 78, 78, 100, 22, 78, 100,
100, 100, 78, 100, 100, 100, 78, 78, 21, 31, 78, 78, 13, 22, 78,
100, 100, 100, 78, 21, 100, 13, 21, 22, 31, 31, 31, 100, 78,
100, 13, 22, 21, 22, 100, 78
],
"y": [
9, 9, 6, 8, 8, 5, 7, 9, 8, 9, 8, 7, 9, 8, 9, 8, 8, 9, 5, 7, 9,
8, 9, 3, 9, 9, 9, 9, 8, 9, 9, 9, 8, 9, 9, 5, 3, 8, 8, 9, 5, 9,
7, 9, 6, 2, 8, 9, 8, 8, 8, 9, 9, 4, 8, 9, 8, 9, 6, 9, 8, 9, 7,
8, 9, 9, 8, 7, 9, 9, 9, 8, 9, 9, 8, 5, 9, 5, 9, 8, 9, 5, 5, 9,
9, 9, 1, 7, 9, 8, 9, 8, 8, 4, 5, 8, 6, 9, 6, 9, 7, 7, 7, 8, 9,
7, 7, 9, 6, 7, 8, 9, 8, 9, 9, 9, 8, 9, 9, 7, 5, 6, 8, 8, 8, 6,
4, 9, 7, 9, 8, 7, 8, 5, 9, 5, 7, 8, 9, 8, 7, 9, 8, 8, 6, 8, 5,
9, 9, 9, 7, 8, 9, 8, 9, 6, 6, 8, 9, 8, 8, 4, 8, 9, 7, 8, 9, 8,
7, 9, 4, 9, 6, 4, 4, 8, 8, 9, 8, 8, 8, 9, 9, 6, 8, 5, 4, 5, 6,
8, 5, 4, 6, 9, 8, 7, 7, 4, 8, 8, 9, 9, 9, 8, 9, 9, 9, 5, 9, 7,
9, 7, 6, 9, 8, 6, 9, 9, 9, 8, 7, 9, 8, 7, 8, 9, 8, 8, 8, 9, 6,
8, 9, 9, 9, 8, 9, 9, 9, 8, 8, 5, 7, 8, 8, 4, 6, 8, 9, 9, 9, 8,
5, 9, 4, 5, 6, 7, 7, 7, 9, 8, 9, 4, 6, 5, 6, 9, 8
],
"text": [
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 2",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 2",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 1",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 13",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 1",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 13",
"Number of parks = 21",
"Number of parks = 78",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 21",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 22",
"Number of parks = 13",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 13",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 13",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 13",
"Number of parks = 13",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 13",
"Number of parks = 21",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 13",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 13",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 31",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 31",
"Number of parks = 78",
"Number of parks = 78",
"Number of parks = 13",
"Number of parks = 22",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 21",
"Number of parks = 100",
"Number of parks = 13",
"Number of parks = 21",
"Number of parks = 22",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 31",
"Number of parks = 100",
"Number of parks = 78",
"Number of parks = 100",
"Number of parks = 13",
"Number of parks = 22",
"Number of parks = 21",
"Number of parks = 22",
"Number of parks = 100",
"Number of parks = 78"
],
"type": "bar",
"textposition": "none",
"marker": {
"autocolorscale": false,
"color": "rgba(89,89,89,1)",
"line": { "width": 1.88976377952756, "color": "transparent" }
},
"showlegend": false,
"xaxis": "x",
"yaxis": "y",
"hoverinfo": "text",
"frame": null
}
],
"layout": {
"margin": {
"t": 26.2283105022831,
"r": 7.30593607305936,
"b": 40.1826484018265,
"l": 92.7853881278539
},
"plot_bgcolor": "rgba(235,235,235,1)",
"paper_bgcolor": "rgba(255,255,255,1)",
"font": {
"color": "rgba(0,0,0,1)",
"family": "",
"size": 14.6118721461187
},
"xaxis": {
"domain": [0, 1],
"automargin": true,
"type": "linear",
"autorange": false,
"range": [-5, 105],
"tickmode": "array",
"ticktext": ["0", "25", "50", "75", "100"],
"tickvals": [0, 25, 50, 75, 100],
"categoryorder": "array",
"categoryarray": ["0", "25", "50", "75", "100"],
"nticks": null,
"ticks": "outside",
"tickcolor": "rgba(51,51,51,1)",
"ticklen": 3.65296803652968,
"tickwidth": 0.66417600664176,
"showticklabels": true,
"tickfont": {
"color": "rgba(77,77,77,1)",
"family": "",
"size": 11.689497716895
},
"tickangle": -0,
"showline": false,
"linecolor": null,
"linewidth": 0,
"showgrid": true,
"gridcolor": "rgba(255,255,255,1)",
"gridwidth": 0.66417600664176,
"zeroline": false,
"anchor": "y",
"title": {
"text": "Number of parks",
"font": {
"color": "rgba(0,0,0,1)",
"family": "",
"size": 14.6118721461187
}
},
"hoverformat": ".2f"
},
"yaxis": {
"domain": [0, 1],
"automargin": true,
"type": "linear",
"autorange": false,
"range": [0.4, 9.6],
"tickmode": "array",
"ticktext": [
"OTHER",
"SPECIAL",
"SPORTS COMPLEX",
"TRAFFICWAY",
"CONSERVATION",
"OPEN SPACE",
"COMMUNITY",
"NEIGHBORHOOD",
"MINI"
],
"tickvals": [1, 2, 3, 4, 5, 6, 7, 8, 9],
"categoryorder": "array",
"categoryarray": [
"OTHER",
"SPECIAL",
"SPORTS COMPLEX",
"TRAFFICWAY",
"CONSERVATION",
"OPEN SPACE",
"COMMUNITY",
"NEIGHBORHOOD",
"MINI"
],
"nticks": null,
"ticks": "outside",
"tickcolor": "rgba(51,51,51,1)",
"ticklen": 3.65296803652968,
"tickwidth": 0.66417600664176,
"showticklabels": true,
"tickfont": {
"color": "rgba(77,77,77,1)",
"family": "",
"size": 11.689497716895
},
"tickangle": -0,
"showline": false,
"linecolor": null,
"linewidth": 0,
"showgrid": true,
"gridcolor": "rgba(255,255,255,1)",
"gridwidth": 0.66417600664176,
"zeroline": false,
"anchor": "x",
"title": {
"text": "",
"font": { "color": null, "family": null, "size": 0 }
},
"hoverformat": ".2f"
},
"shapes": [
{
"type": "rect",
"fillcolor": null,
"line": { "color": null, "width": 0, "linetype": [] },
"yref": "paper",
"xref": "paper",
"x0": 0,
"x1": 1,
"y0": 0,
"y1": 1
}
],
"showlegend": false,
"legend": {
"bgcolor": "rgba(255,255,255,1)",
"bordercolor": "transparent",
"borderwidth": 1.88976377952756,
"font": {
"color": "rgba(0,0,0,1)",
"family": "",
"size": 11.689497716895
}
},
"hovermode": "closest",
"barmode": "relative"
},
"config": {
"doubleClick": "reset",
"modeBarButtonsToAdd": ["hoverclosest", "hovercompare"],
"showSendToCloud": false
},
"source": "A",
"attrs": {
"e434646d209": { "x": {}, "y": {}, "text": {}, "type": "bar" }
},
"cur_data": "e434646d209",
"visdat": { "e434646d209": ["function (y) ", "x"] },
"highlight": {
"on": "plotly_click",
"persistent": false,
"dynamic": false,
"selectize": false,
"opacityDim": 0.2,
"selected": { "opacity": 1 },
"debounce": 0
},
"shinyEvents": [
"plotly_hover",
"plotly_click",
"plotly_selected",
"plotly_relayout",
"plotly_brushed",
"plotly_brushing",
"plotly_clickannotation",
"plotly_doubleclick",
"plotly_deselect",
"plotly_afterplot",
"plotly_sunburstclick"
],
"base_url": "https://plot.ly"
},
"evals": [],
"jsHooks": []
}
&lt;/script>
&lt;p class="caption">Figure 1: Number of parks within each type.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="twenty-largest-parks" class="section level2">
&lt;h2>Twenty largest parks&lt;/h2>
&lt;p>
&lt;font style="color: grey"
>[Placeholder text] Lorem ipsum dolor sit amet, consectetur adipiscing
elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.&lt;/font
>
Table &lt;a href="#tab:largest-parks">1&lt;/a> shows the twenty largest parks
types, along with their type and acreage. The code doesn’t show below
because &lt;code>echo = FALSE&lt;/code>.
&lt;/p>
&lt;table>
&lt;caption>
&lt;span id="tab:largest-parks">Table 1: &lt;/span
>The twenty largest parks in Madison.
&lt;/caption>
&lt;thead>
&lt;tr class="header">
&lt;th align="left">Name&lt;/th>
&lt;th align="left">Type&lt;/th>
&lt;th align="right">Acreage&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="left">Cherokee Marsh - North Unit&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">946.58&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Cherokee Marsh - South Unit (School Road Unit)&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">261.27&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Elver Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">250.82&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Northeast Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">237.76&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Warner Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">213.49&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Door Creek Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">159.97&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Cherokee Marsh - Mendota Unit&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">122.08&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Owen Conservation Park&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">96.79&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Reindahl (Amund) Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">90.74&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Olbrich Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">90.01&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Yahara Hills Park (West)&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">82.20&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Sycamore Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">71.42&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Turville Point Conservation Park&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">64.28&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Edna Taylor Conservation Park&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">60.27&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Quann Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">55.43&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Demetral Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">49.18&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Prairie Ridge Conservation Park&lt;/td>
&lt;td align="left">CONSERVATION&lt;/td>
&lt;td align="right">48.76&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Olin Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">47.12&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="left">Hiestand Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">46.27&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="left">Vilas (Henry) Park&lt;/td>
&lt;td align="left">COMMUNITY&lt;/td>
&lt;td align="right">45.67&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>
We could decide to display the code for the table at this point (or any
other), which can be done using the parameters
&lt;code>ref.label = 'largest-parks', echo = TRUE, eval = FALSE&lt;/code> in the
chunk options (&lt;a
href="https://bookdown.org/yihui/rmarkdown-cookbook/reuse-chunks.html"
>Xie, Dervieux, &amp;amp; Riederer, 2020&lt;/a
>).
&lt;/p>
&lt;pre class="r">&lt;code>dat %&amp;gt;%
summarize(Name = Park_Name, Type, Acreage) %&amp;gt;%
arrange(-Acreage, Name, Type) %&amp;gt;%
select(Name, Type, Acreage) %&amp;gt;%
head(20) %&amp;gt;%
kable(caption = &amp;#39;The twenty largest parks in Madison.&amp;#39;)&lt;/code>&lt;/pre>
&lt;/div></description><category>s</category><category>R</category><category>R Markdown</category><category>CarpentryCon</category><category>workshop</category><category>RStudio</category><category>bookdown</category><category>cross-references</category><category>programming</category><category>R</category></item><item><title>Web application for the simulation of experimental data</title><link>https://pablobernabeu.github.io/applications-and-dashboards/experimental-data-simulation/</link><pubDate>Mon, 01 Jun 2020 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/applications-and-dashboards/experimental-data-simulation/</guid><description>
&lt;div style="font-size: 25px; color: #614064; padding-top: 15px; padding-bottom: 10px;">
&lt;i class="fas fa-chalkboard-teacher fa-xs" aria-hidden="true">&lt;/i>&amp;nbsp;&lt;i class="fas fa-university fa-xs" aria-hidden="true">&lt;/i>&amp;nbsp;Purposes
&lt;/div>
&lt;p>This open-source, R-based web application is suitable for educational and research purposes in experimental and quantitative sciences. It allows the &lt;strong>creation of varied data sets with specified structures, such as between-group and within-participant variables, that can be categorical or continuous.&lt;/strong> These parameters can be set throughout the various tabs (sections) from the top menu. In the last tab, the data set can be downloaded. The benefits of this application include time-saving and flexibility in the control of parameters.&lt;/p>
&lt;div id="how-it-works" class="section level3">
&lt;h3>How it works&lt;/h3>
&lt;div class="mermaid">
graph TD
A["Set parameters across tabs"] --> B["Define between-group&lt;br/>variables"]
A --> C["Define within-participant&lt;br/>variables"]
B --> D["Choose categorical&lt;br/>or continuous"]
C --> D
D --> E["Simulated data set"]
E --> F["Build custom summary&lt;br/>(penultimate tab)"]
F --> G["Download parameters and&lt;br/>data set (last tab)"]
&lt;/div>
&lt;/div>
&lt;div id="guidelines" class="section level3">
&lt;h3>Guidelines&lt;/h3>
&lt;p>General guidelines include the following:&lt;/p>
&lt;ul>
&lt;li>&lt;p>&lt;strong>In the names of variables&lt;/strong>, it is recommended to use only alphanumeric characters and underscore signs. The latter can be used to separate characters or words (e.g., &lt;em>variable_name&lt;/em>). Different names should be used for each variable.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>In the levels of categorical variables&lt;/strong>, alphanumeric, special characters and spaces are allowed.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>In numeric fields&lt;/strong> (e.g., ‘Mean’, ‘Standard deviation’, ‘Relative probability [0, 1]’), only numbers and decimal points are allowed.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>As the data set increases&lt;/strong>, so does the processing time.&lt;/p>&lt;/li>
&lt;/ul>
&lt;p>More specific guidelines are available in each section.&lt;/p>
&lt;/div>
&lt;div id="the-web-application-can-be-launched-here." class="section level3">
&lt;h3>&lt;i class="fa-solid fa-globe">&lt;/i>&amp;nbsp;The web application can be &lt;a href="https://pablo-bernabeu.shinyapps.io/experimental-data-simulation/">launched here&lt;/a>.&lt;/h3>
&lt;div style="padding-top:8px; padding-bottom:2px; margin-bottom:-20px; color:#665F5F;">
Screenshot of the &lt;em>Dependent&lt;/em> tab (&lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation/raw/master/Screenshot.png">view larger&lt;/a>)
&lt;/div>
&lt;p>&lt;img style="max-width: 800px; display: block; margin-left: auto; margin-right: auto; padding-bottom: 15px;" src="https://github.com/pablobernabeu/Experimental-data-simulation/raw/master/Screenshot.png" alt="Screenshot of the Dependent tab in the experimental data simulation web app, showing parameter settings for the dependent variable" />&lt;/p>
&lt;/div>
&lt;div id="reference" class="section level3">
&lt;h3>Reference&lt;/h3>
&lt;p>Bernabeu, P., &amp;amp; Lynott, D. (2020). &lt;em>Web application for the simulation of experimental data&lt;/em> (Version 1.4). &lt;a href="https://github.com/pablobernabeu/Experiment-simulation-app/">https://github.com/pablobernabeu/Experiment-simulation-app/&lt;/a>&lt;/p>
&lt;/div>
&lt;div id="code" class="section level3">
&lt;h3>Code&lt;/h3>
&lt;p>This web application was developed in &lt;a href="https://www.r-project.org/about.html">R&lt;/a> (R Core Team, 2020). The code is &lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation/blob/master/index.Rmd">available on Github&lt;/a>, where contributions may be made. The initial code for this application was influenced by Section 5.7 (&lt;a href="https://crumplab.github.io/programmingforpsych/simulating-and-analyzing-data-in-r.html#simulating-data-for-multi-factor-designs" target="_blank">&lt;em>Simulating data for multi-factor designs&lt;/em>&lt;/a>) in Crump (2017). The R packages used include ‘dplyr’ (Wickham, François, Henry, &amp;amp; Müller, 2018), ‘DT’ (Xie, 2020), ‘flexdashboard’ (Iannone, Allaire, &amp;amp; Borges, 2020), ‘shiny’ (Chang, Cheng, Allaire, Xie, &amp;amp; McPherson, 2020) and ‘stringr’ (Wickham, 2019).&lt;/p>
&lt;/div>
&lt;div id="options-for-development-and-local-use-of-the-app" class="section level3">
&lt;h3>Options for development and local use of the app&lt;/h3>
&lt;div id="option-a-using-local-rrstudio-or-rstudio-cloud-project-or-binder-rstudio-environment" class="section level4">
&lt;h4>Option A) Using local R/RStudio or &lt;a href="https://rstudio.cloud/project/1739958">RStudio Cloud project&lt;/a> or &lt;a href="https://mybinder.org/v2/gh/pablobernabeu/Experimental-data-simulation/master?urlpath=rstudio">Binder RStudio environment&lt;/a>&lt;/h4>
&lt;ol style="list-style-type: decimal">
&lt;li>&lt;p>[Step only necessary in R/RStudio] Install the packages in the versions used in the &lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation/releases">latest release of this application&lt;/a>, by running:&lt;/p>
&lt;pre>&lt;code>install.packages(&amp;#39;devtools&amp;#39;)
library(devtools)
install_version(&amp;#39;dplyr&amp;#39;, &amp;#39;1.0.2&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;DT&amp;#39;, &amp;#39;0.15&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;flexdashboard&amp;#39;, &amp;#39;0.5.2&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;htmltools&amp;#39;, &amp;#39;0.5.0&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;knitr&amp;#39;, &amp;#39;1.30&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;ngram&amp;#39;, &amp;#39;3.0.4&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;purrr&amp;#39;, &amp;#39;0.3.4&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;shiny&amp;#39;, &amp;#39;1.5.0&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;stringr&amp;#39;, &amp;#39;1.4.0&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)
install_version(&amp;#39;tidyr&amp;#39;, &amp;#39;1.1.2&amp;#39;, &amp;#39;http://cran.us.r-project.org&amp;#39;)&lt;/code>&lt;/pre>&lt;/li>
&lt;li>&lt;p>Open the &lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation/blob/master/index.Rmd">index.Rmd&lt;/a> script.&lt;/p>&lt;/li>
&lt;li>&lt;p>Run the application by clicking on &lt;kbd>▶️ Run document&lt;/kbd> at the top left, or by running &lt;code>rmarkdown::run('index.Rmd')&lt;/code> in the console.&lt;/p>&lt;/li>
&lt;li>&lt;p>Click on &lt;kbd>Open in Browser&lt;/kbd> at the top left.&lt;/p>&lt;/li>
&lt;/ol>
&lt;/div>
&lt;div id="option-b-using-dockerfile-see-instructions" class="section level4">
&lt;h4>Option B) Using Dockerfile (&lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation#option-b-using-dockerfile-vsochs-pull-request">see instructions&lt;/a>)&lt;/h4>
&lt;/div>
&lt;/div>
&lt;div id="acknowledgements" class="section level3">
&lt;h3>Acknowledgements&lt;/h3>
&lt;p>Thank you to RStudio for the free hosting server used by this application, &lt;a href="https://www.shinyapps.io/">shinyapps.io&lt;/a>.&lt;/p>
&lt;/div>
&lt;div id="references" class="section level3">
&lt;h3>References&lt;/h3>
&lt;p>Chang, W., Cheng, J., Allaire, J., Xie, Y., &amp;amp; McPherson, J. (2020). shiny: Web Application Framework for R. R package version 1.4.0. Available at &lt;a href="http://CRAN.R-project.org/package=shiny">http://CRAN.R-project.org/package=shiny&lt;/a>.&lt;/p>
&lt;p>Crump, M. J. C. (2017). Programming for Psychologists: Data Creation and Analysis (Version 1.1). &lt;a href="https://crumplab.github.io/programmingforpsych/">https://crumplab.github.io/programmingforpsych/&lt;/a>.&lt;/p>
&lt;p>Iannone, R., Allaire, J. J., &amp;amp; Borges, B. (2020). Flexdashboard: R Markdown Format for Flexible Dashboards. &lt;a href="http://rmarkdown.rstudio.com/flexdashboard">http://rmarkdown.rstudio.com/flexdashboard&lt;/a>.&lt;/p>
&lt;p>R Core Team (2020). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. URL &lt;a href="https://www.R-project.org/">https://www.R-project.org/&lt;/a>.&lt;/p>
&lt;p>Wickham, H. (2019). stringr: Simple, Consistent Wrappers for Common String Operations. R package version 1.4.0. &lt;a href="https://CRAN.R-project.org/package=stringr">https://CRAN.R-project.org/package=stringr&lt;/a>.&lt;/p>
&lt;p>Wickham, H., François, R., Henry, L., &amp;amp; Müller, K. (2018). dplyr: A Grammar of Data Manipulation. R package version 0.7.6. &lt;a href="https://CRAN.R-project.org/package=dplyr">https://CRAN.R-project.org/package=dplyr&lt;/a>.&lt;/p>
&lt;p>Xie, Y. (2020). DT: A Wrapper of the JavaScript Library “DataTables”. R package version 0.14. Available at &lt;a href="https://CRAN.R-project.org/package=DT">https://CRAN.R-project.org/package=DT&lt;/a>.&lt;/p>
&lt;/div>
&lt;div id="contact" class="section level3">
&lt;h3>Contact&lt;/h3>
&lt;p>To submit any questions or feedback, please post &lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation/issues">an issue&lt;/a>, or email Pablo Bernabeu at &lt;a href="mailto:pcbernabeu@gmail.com">pcbernabeu@gmail.com&lt;/a>.&lt;/p>
&lt;/div></description><category>web application</category><category>data simulation</category><category>randomisation</category><category>research methods</category><category>experiment</category><category>statistics</category><category>data science</category><category>R</category><category>Tidyverse</category><category>R Shiny</category><category>Flexdashboard</category><category>HTML</category><category>CSS</category><category>Software Sustainability Institute Fellowship</category><category>web application</category><category>research and teaching applications</category><category>R</category></item><item><title>Data dashboard: Butterfly species richness in Los Angeles</title><link>https://pablobernabeu.github.io/applications-and-dashboards/butterfly-species-richness-in-la/</link><pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/applications-and-dashboards/butterfly-species-richness-in-la/</guid><description>&lt;a href='https://pablobernabeu.github.io/dashboards/Butterfly-species-richness-in-LA'>
&lt;button style = "background-color: white; color: black; border: 2px solid #196F27; border-radius: 12px;">
&lt;h3 style = "margin-top: 7px !important; margin-left: 9px !important; margin-right: 9px !important;">
&lt;span style="color:#DBE6DA;">&lt;/span> Dashboard
&lt;/h3>&lt;/button>
&lt;/a>
&lt;br>
&lt;br>
&lt;h3 id="how-it-works">How it works&lt;/h3>
&lt;div class="mermaid">
graph TD
A["Open data from&lt;br/>Prudic et al. (2018)"] --> B["iNaturalist (citizen science)"]
A --> C["BioScan (traditional traps)"]
B --> D["Transform, merge,&lt;br/>and wrangle in R"]
C --> D
D --> E["Dashboard: butterfly species&lt;br/>richness in Los Angeles"]
&lt;/div>
&lt;p>This dashboard presents open data (&lt;a href='https://github.com/jcoliver/bioscan/blob/master/data/iNaturalist-clean-reduced.csv'>iNaturalist&lt;/a> and &lt;a href='https://github.com/jcoliver/bioscan/blob/master/data/BioScanDataComplete.csv'>BioScan&lt;/a>) from
&lt;a href="https://doi.org/10.3390/insects9040186">Prudic et al. (2018)&lt;/a>. In their study, Prudic et al. compared citizen science with traditional methods in the measurement of butterfly populations.&lt;/p>
&lt;p>I developed this dashboard after reproducing the
&lt;a href="https://github.com/jcoliver/bioscan">analyses of the original study&lt;/a> in a
&lt;a href="https://github.com/reprohack/reprohack-hq/blob/master/README.md">Reprohack session&lt;/a>.&lt;/p>
&lt;p>My coding tasks included transforming the data to a long format,&lt;/p>
&lt;pre>&lt;code># There are pseudovariables, that is, observations entered as variables.
# Since most R processes need the tidy format, convert below
# (see https://r4ds.had.co.nz/tidy-data.html). The specific numbers
# found through traps and crowdsourcing methods are preserved.
BioScan = BioScan %&amp;gt;% pivot_longer(
cols = Anthocharis_sara:Vanessa_cardui, names_to = &amp;quot;Species&amp;quot;,
values_to = &amp;quot;Number&amp;quot;, values_drop_na = TRUE
)
# Compare
#str(BioScan)
#str(dat)
# 928 rows now; the result of 29 pseudo-variables being transposed
# into rows, interacting with 32 previous rows, i.e., 29 * 32 = 928.
&lt;/code>&lt;/pre>
&lt;p>merging three data sets,&lt;/p>
&lt;pre>&lt;code># The iNaturalist data set presents a challenge that differs from the
# pseudovariables found above. The number of animals of each species
# must be computed from repeated entries, per site.
iNaturalist = merge(iNaturalist,
iNaturalist %&amp;gt;%
count(species, site, name = 'Number'))
&lt;/code>&lt;/pre>
&lt;p>and, as ever, wrangling with the format of the dashboard pages to preserve the format of a table.&lt;/p>
&lt;pre>&lt;code>Species details {style=&amp;quot;background-color: #FCFCFC;&amp;quot;}
=======================================================================
Column {style=&amp;quot;data-width:100%; position:static; height:1000px;&amp;quot;}
-----------------------------------------------------------------------
&lt;/code>&lt;/pre>
&lt;h3 id="reference">Reference&lt;/h3>
&lt;p>Prudic, K. L., Oliver, J. C., Brown, B. V., &amp;amp; Long, E. C. (2018). Comparisons of citizen science data-gathering approaches to evaluate urban butterfly diversity. &lt;em>Insects, 9&lt;/em>(4), 186. &lt;a href="https://doi.org/10.3390/insects9040186">https://doi.org/10.3390/insects9040186&lt;/a>&lt;/p></description><category>data dashboard</category><category>R</category><category>citizen science</category><category>butterflies</category><category>nature</category><category>open data</category><category>BioScan</category><category>iNaturalist</category><category>HTML</category><category>CSS</category><category>tidy</category><category>merge</category><category>Software Sustainability Institute Fellowship</category><category>web application</category><category>research and teaching applications</category><category>data visualisation</category><category>R</category></item><item><title>Data is present: Workshops and datathons</title><link>https://pablobernabeu.github.io/2020/data-is-present-workshops-and-datathons/</link><pubDate>Wed, 01 Jan 2020 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2020/data-is-present-workshops-and-datathons/</guid><description>
&lt;div id="enhanced-data-presentation-using-reproducible-documents-and-dashboards" class="section level2">
&lt;h2>Enhanced data presentation using reproducible documents and dashboards&lt;/h2>
&lt;div id="calendar" class="section level3">
&lt;h3>Calendar&lt;/h3>
&lt;table>
&lt;colgroup>
&lt;col width="9%" />
&lt;col width="23%" />
&lt;col width="39%" />
&lt;col width="27%" />
&lt;/colgroup>
&lt;thead>
&lt;tr class="header">
&lt;th align="center">Date&lt;/th>
&lt;th>Title&lt;/th>
&lt;th>Event and location&lt;/th>
&lt;th>Registration&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr class="odd">
&lt;td align="center">26 Nov 2020&lt;/td>
&lt;td>&lt;a href="https://pablobernabeu.github.io/presentation/2020-11-26-mixed-effects-models-in-r-and-a-new-tool-for-data-simulation">Mixed-effects models in R, and a new tool for data simulation&lt;/a>&lt;/td>
&lt;td>New Tricks Seminars, Dept. Psychology, Lancaster University [online]&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="center">8 Oct 2020&lt;/td>
&lt;td>&lt;a href="https://pablobernabeu.github.io/presentation/2020-10-08-reproducibilidad-en-torno-a-una-aplicacion-web/">Reproducibilidad en torno a una aplicación web&lt;/a>&lt;/td>
&lt;td>Reprohack en español, LatinR Conference 2020 [online]&lt;/td>
&lt;td>&lt;a href="https://www.eventbrite.com.ar/e/reprohack-en-espanol-latinr-2020-tickets-121741832097">Link&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="center">13 Aug 2020&lt;/td>
&lt;td>&lt;a href="https://github.com/pablobernabeu/CarpentryCon-2020-workshop-Open-Data-Reproducibility">Open data and reproducibility: R Markdown, data dashboards and Binder v2.1&lt;/a> (co-led with Florencia D’Andrea)&lt;/td>
&lt;td>&lt;a href="https://2020.carpentrycon.org/schedule/">CarpentryCon@Home&lt;/a>, The Carpentries [online]&lt;/td>
&lt;td>&lt;a href="https://2020.carpentrycon.org/schedule/">Link&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="center">26 July 2020&lt;/td>
&lt;td>&lt;a href="https://github.com/pablobernabeu/UKCLC2020-workshop-Open-data-and-reproducibility">Open data and reproducibility: R Markdown, data dashboards and Binder&lt;/a> (co-led with Eirini Zormpa)&lt;/td>
&lt;td>&lt;a href="https://www.ukclc2020.com/pre-conference">UK Cognitive Linguistics Conference&lt;/a>, University of Birmingham [online]&lt;/td>
&lt;td>&lt;a href="https://www.ukclc2020.com/registration">Link&lt;/a>&lt;/td>
&lt;/tr>
&lt;tr class="odd">
&lt;td align="center">6 May 2020&lt;/td>
&lt;td>&lt;a href="https://pablobernabeu.github.io/PDF/LU-May-Markdown-workshop-programme.pdf">R Markdown&lt;/a>&lt;/td>
&lt;td>Lancaster University [online]&lt;/td>
&lt;td>&lt;/td>
&lt;/tr>
&lt;tr class="even">
&lt;td align="center">Event cancelled&lt;/td>
&lt;td>&lt;a href="https://newcastle2020.satrdays.org/">Open data and reproducibility 2.0&lt;/a>&lt;/td>
&lt;td>&lt;a href="https://newcastle2020.satrdays.org/">SatRday Newcastle upon Tyne&lt;/a>, Newcastle University&lt;/td>
&lt;td>&lt;a href="https://newcastle2020.satrdays.org/">Link&lt;/a>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;div style="margin-top: 5%;">
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="background" class="section level2">
&lt;h2>Background&lt;/h2>
&lt;p>This project offers free activities to learn and practise reproducible data presentation. &lt;a href="https://www.software.ac.uk/about/fellows/pablo-bernabeu">Pablo Bernabeu&lt;/a> organises these events in the context of a &lt;a href="https://www.software.ac.uk/programmes-and-events/fellowship-programme">Software Sustainability Institute Fellowship&lt;/a>.&lt;/p>
&lt;div id="open-source-software" class="section level4">
&lt;h4>Open-source software&lt;/h4>
&lt;p>Programming languages such as &lt;a href="https://www.r-project.org/about.html">R&lt;/a> and &lt;a href="https://www.python.org/">Python&lt;/a> offer free, powerful resources for data processing, visualisation and analysis. Experience in these programs is highly valued in data-intensive disciplines.&lt;/p>
&lt;/div>
&lt;div id="open-data" class="section level4">
&lt;h4>Open data&lt;/h4>
&lt;p>Original data has become a &lt;a href="https://www.nature.com/articles/d41586-019-01506-x">public good in many research fields&lt;/a> thanks to cultural and technological advances. On the internet, we can find innumerable data sets from sources such as scientific journals and repositories (e.g., &lt;a href="https://osf.io">OSF&lt;/a>), local and national governments (e.g., &lt;a href="https://data.london.gov.uk/">London&lt;/a>, UK [&lt;a href="https://www.ukdataservice.ac.uk/">1&lt;/a>, &lt;a href="https://data.gov.uk/">2&lt;/a>]), non-governmental organisations (e.g., &lt;a href="https://data.world/datasets/ngo">data.world&lt;/a>), etc. Researchers inside and outside academia nowadays share a lot of their data under attribution licences (e.g., &lt;a href="https://creativecommons.org/">Creative Commons&lt;/a>, the UK &lt;a href="http://www.nationalarchives.gov.uk/doc/open-government-licence/version/1/">Open Government Licence&lt;/a>, etc.). This allows any external analysts to access these raw data, create (additional) visualisations and analyses, and share these. In society, making data more accessible can &lt;a href="https://digitalcommons.law.yale.edu/cgi/viewcontent.cgi?article=1140&amp;amp;context=yhrdlj">demonstrably benefit citizens&lt;/a> (despite &lt;a href="https://firstmonday.org/ojs/index.php/fm/article/view/3316/2764#author">limitations&lt;/a>).&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="activities" class="section level2">
&lt;h2>Activities&lt;/h2>
&lt;p>Activities comprise free &lt;strong>workshops&lt;/strong> and &lt;a href="#datathons-creating-reproducible-documents-and-dashboards">&lt;strong>datathons&lt;/strong>&lt;/a>.&lt;/p>
&lt;div id="workshops" class="section level3">
&lt;h3>Workshops&lt;/h3>
&lt;p>&lt;a href="https://www.r-project.org">R is a programming language&lt;/a> greatly equipped for the creation of reproducible documents and dashboards. Four workshops are offered that cover a suite of interrelated tools—R, R Markdown, data dashboards and Binder environments—, all underlain by reproducible workflows and open-source software.&lt;/p>
&lt;p>Each workshop includes &lt;strong>taught and practical sections&lt;/strong>. The practice provides a chance for participants to experience and address common issues with the code. The level of taught sections is largely tailored to participants; similarly, practice sections are individually adaptable by means of easier and tougher tasks. The duration is also flexible, and some of the workshops can be combined into the same session.&lt;/p>
&lt;p>The &lt;a href="https://rstudio.com/">RStudio&lt;/a> interface is used in all workshops. Multi-levelled, real code examples are used. Throughout the workshops, and especially in the practice sections, individual questions will be encouraged.&lt;/p>
&lt;div id="workshop-1-introduction-to-r" class="section level4">
&lt;h4>Workshop 1: Introduction to R&lt;/h4>
&lt;p>This workshop can serve as an introduction to R or a revision. It demonstrates what can be done in R, and provides resources for individual training. Since the duration is limited, online courses are also recommended (&lt;a href="https://www.coursera.org/courses?query=r">see examples&lt;/a> and &lt;a href="https://learner.coursera.help/hc/en-us/articles/209819033-Apply-for-Financial-Aid-or-a-Scholarship">fee waivers for full content&lt;/a>).&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://adv-r.had.co.nz/Data-structures.html">Data structures&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.sthda.com/english/wiki/installing-and-using-r-packages">Packages&lt;/a>: general-purpose examples (e.g., &lt;a href="https://www.tidyverse.org/">tidyverse&lt;/a>) and more specific ones (e.g., for &lt;a href="https://cran.r-project.org/web/packages/lsr/lsr.pdf">statistics&lt;/a> or &lt;a href="https://cran.r-project.org/web/packages/GEOmap/GEOmap.pdf">geography&lt;/a>)&lt;/li>
&lt;li>&lt;a href="https://cran.r-project.org/web/packages/rio/vignettes/rio.html">Loading and writing data, in native and foreign formats&lt;/a>&lt;/li>
&lt;li>&lt;em>Tidy&lt;/em> format&lt;/li>
&lt;li>&lt;em>Wide&lt;/em> versus &lt;em>long&lt;/em> format. For most processes in R, &lt;a href="https://r4ds.had.co.nz/tidy-data.html">data needs to be in a tidy, long format&lt;/a>.&lt;/li>
&lt;/ul>
&lt;p align="center">
&lt;a href = 'https://doi.org/10.1371/journal.pbio.3000202.g001'>&lt;img width = '45%' src = 'https://journals.plos.org/plosbiology/article/file?id=10.1371/journal.pbio.3000202.g001&amp;type=large' alt = 'Illustration of wide and tidy data formats, from Postma and Goedhart (2019)' style = 'margin-top:-0.1px;' />&lt;/a>
&lt;p align="center" style="font-size:80%; color:darkgrey; text-align:center; margin-top:-24px; margin-bottom:20px;">
Illustration from &lt;a href="https://doi.org/10.1371/journal.pbio.3000202.g001">Postma and Goedhart (2019)&lt;/a>.
&lt;/p>
&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://psyteachr.github.io/msc-data-skills/joins.html#joins">Combining data sets&lt;/a>&lt;/li>
&lt;li>&lt;a href="http://www.cookbook-r.com/Manipulating_data/Summarizing_data/">Data summaries&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://philmcaleer.github.io/ug2-practical/visualisation-through-ggplot2.html">Plots with &lt;code>ggplot2::ggplot()&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://plot.ly/ggplot2/">Interactive plots with &lt;code>plotly::ggplotly()&lt;/code>&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://learningstatisticswithr-bookdown.netlify.com/part-v-statistical-tools.html">Statistics&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://psych.wisc.edu/Brauer/BrauerLab/wp-content/uploads/2014/04/Brauer_and_Curtin_LMEMs-2017-Psych_Methods.pdf">Linear mixed-effects models&lt;/a> (see also &lt;a href="https://www.sciencedirect.com/science/article/pii/S0749596X20300061?dgcid=coauthor#b0670">a review of practices&lt;/a>)&lt;/li>
&lt;li>&lt;a href="https://swcarpentry.github.io/r-novice-inflammation/02-func-R/">How functions work&lt;/a>&lt;/li>
&lt;li>&lt;em>Debugging&lt;/em>. Code errors are known as bugs. They can tiresome, but also interesting sometimes! :sweat_smile: Some tips for the first many years of experience include: reading and investigating error messages, in both source and console windows; controlling letter case and typos; closing parentheses and inverted commas; ensuring to have the necessary packages installed and loaded; following the format required by each function. To debug, break up code into subcomponents and test each of those to find out the source of the error. Once we act on that, the best outcome is seeing the code work, but sometimes different errors overlap, in which case we may see one error disappearing before another one appears. Debugging soon leads to proficient information seeking. The search process often begins on an internet search engine and extends to user communities, package documentation, tutorials, blogs… (see &lt;a href="https://youtu.be/Nj9J5iCSMB0?t=2687">video explanation&lt;/a>). &lt;a href="https://adv-r.hadley.nz/debugging.html">Advanced debugging tools are also available&lt;/a>.&lt;/li>
&lt;li>Vast availability of free resources on the internet, from &lt;a href="https://www.coursera.org/courses?query=r%20programming">Coursera&lt;/a> and other MOOC sites, &lt;a href="https://education.rstudio.com/">RStudio&lt;/a>, &lt;a href="https://psyteachr.github.io/">University of Glasgow&lt;/a>, &lt;a href="http://swcarpentry.github.io/r-novice-inflammation/">Carpentries&lt;/a>, etc.&lt;/li>
&lt;li>Community: &lt;a href="https://stackoverflow.com/">StackOverflow&lt;/a>, &lt;a href="https://community.rstudio.com/">RStudio Community&lt;/a>, &lt;a href="https://github.com">Github issues&lt;/a> (e.g., for R packages), etc. Using and contributing back.&lt;/li>
&lt;li>&lt;a href="https://rstudio.cloud/">RStudio Cloud&lt;/a>: a personal RStudio environment on the internet&lt;/li>
&lt;/ul>
&lt;/div>
&lt;div id="workshop-2-r-markdown-documents" class="section level4">
&lt;h4>Workshop 2: R Markdown documents&lt;/h4>
&lt;p>Set your input and output in stone using &lt;a href="https://rmarkdown.rstudio.com/">R Markdown&lt;/a>. The analysis reports may be enriched with website features (HTML/CSS) and published as HTML, PDF or Word documents. Moreover, with R packages such as &lt;code>bookdown&lt;/code>, &lt;code>bookdownplus&lt;/code>, &lt;code>blogdown&lt;/code> and &lt;code>flexdashboard&lt;/code>, documents can be formatted as &lt;a href="https://awesome-blogdown.com/">websites&lt;/a>, &lt;a href="https://bookdown.org/">digital papers and books&lt;/a> and &lt;a href="https://rmarkdown.rstudio.com/flexdashboard/">data dashboards&lt;/a>. Other useful packages include &lt;code>rmarkdown&lt;/code>, &lt;code>knitr&lt;/code>, &lt;code>DT&lt;/code>, &lt;code>kableExtra&lt;/code> and &lt;code>ggplot2&lt;/code>. Further background: &lt;a href="https://www.youtube.com/watch?v=Nj9J5iCSMB0">presentation by Michael Frank&lt;/a>, &lt;a href="https://www.eddjberry.com/talks/reproducible-writing-with-rmarkdown.html#1">slides by Ed Berry&lt;/a>.&lt;/p>
&lt;p>As well as facilitating the reproducibility of analyses and results to third parties, R Markdown is helpful &lt;em>during the creation&lt;/em> of a report. In particular, it reduces the chances of errors and the number of repetitive tasks. For instance, any part of the data can be inputted in the text directly from the source, rather than manually copying it (e.g., &lt;code>`r mean(dat[dat$location=='Havana', 'measure'])`&lt;/code> (&lt;a href="https://bookdown.org/yihui/rmarkdown/r-code.html">expand&lt;/a>). Thus, if and when the analysis needs to be changed or updated, the report can be automatically updated at the click of a button. In another area, the captions for figures and tables can be automatised using &lt;a href="https://bookdown.org/yihui/rmarkdown-cookbook/cross-ref.html">cross-reference labels&lt;/a> (e.g., Table &lt;code>\@ref(tab:mtcars)&lt;/code>). This secures the match between the text and the captions of figures and tables, and it automatically updates the numbering whenever and wherever a new figure or table is introduced.&lt;/p>
&lt;p align="center">
&lt;a href = 'https://bookdownplus.netlify.com/portfolio/'>&lt;img width = '50%' src = 'https://github.com/pablobernabeu/bookdownplus/blob/master/inst2/copernicus/showcase/copernicus2.png?raw=true' alt = 'Example of paper created with bookdownplus (image retrieved from R bookdownplus package)'/>&lt;/a>
&lt;p align="center" style="text-align:center; margin-top:-30px; margin-bottom:30px;">
Image from bookdownplus package (&lt;a href="https://bookdownplus.netlify.com/portfolio/" class="uri">https://bookdownplus.netlify.com/portfolio/&lt;/a>).
&lt;/p>
&lt;/p>
&lt;/div>
&lt;div id="workshop-3-introduction-to-data-dashboards" class="section level4">
&lt;h4>Workshop 3: Introduction to data dashboards&lt;/h4>
&lt;p>&lt;a href="https://www.frontiersin.org/articles/10.3389/fpsyg.2015.01782/full">Data dashboards are web applications used to visualise data&lt;/a> in detail through tables and plots. They assist in explaining and accounting for our data processing and analysis. They don’t require any coding from the end user. While most dashboards and web applications present existing data, a few of them serve the purpose of creating or simulating new data (see &lt;a href="https://github.com/pablobernabeu/Experimental-data-simulation">example&lt;/a>).&lt;/p>
&lt;p align="center">
&lt;a href = 'https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/'> &lt;img width = '90%' src = 'https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/8.png' alt = 'Illustration of the usage of dashboards alongside data repositories' /> &lt;/a>
&lt;/p>
&lt;p>These all-reproducible dashboards are published as websites, and thus, they can include hyperlinks and downloadable files. Some of the R packages used are &lt;code>knitr&lt;/code>, &lt;code>DT&lt;/code>, &lt;code>kableExtra&lt;/code>, &lt;code>reactable&lt;/code>, &lt;code>ggplot2&lt;/code>, &lt;code>plotly&lt;/code>, &lt;code>rmarkdown&lt;/code>, &lt;code>flexdashboard&lt;/code> and &lt;code>shiny&lt;/code>. The aim of this workshop is to practise creating different forms of dashboards—&lt;a href="https://rmarkdown.rstudio.com/flexdashboard/">Flexdashboard&lt;/a> and &lt;a href="https://shiny.rstudio.com/">Shiny&lt;/a>—the latter of which offers &lt;a href="https://mastering-shiny.org/">greater features&lt;/a>, and to practise also with the hosting platforms fitting each type—such as personal websites, &lt;a href="https://rpubs.com/">RPubs&lt;/a>, &lt;a href="https://mybinder.org/">Binder&lt;/a>, &lt;a href="https://www.shinyapps.io/">Shinyapps&lt;/a> and &lt;a href="https://rstudio.com/products/shiny/shiny-server/">custom servers&lt;/a>.&lt;/p>
&lt;p>A great thing about dashboards is that they may be made very simple, but they can also be taken to the next level using some HTML, CSS or Javascript code (on top of the back-end code present in the R packages used), which is addressed in the next workshop.&lt;/p>
&lt;/div>
&lt;div id="workshop-4-binder-environments-and-improving-data-dashboards" class="section level4">
&lt;h4>Workshop 4: Binder environments and improving data dashboards&lt;/h4>
&lt;div id="binder" class="section level5">
&lt;h5>Binder&lt;/h5>
&lt;p>&lt;a href="https://mybinder.org/">Binder&lt;/a> is a tool to facilitate public access to software environments—for instance, by publishing an RStudio environment on the internet. Binder can also host Shiny apps. It is generously free &lt;a href="https://discourse.jupyter.org/t/mybinder-org-cost-updates/2426">for users&lt;/a>. After looking at the &lt;a href="https://github.com/binder-examples/r">nuts and bolts of a deployment&lt;/a>, participants will be able to deploy their own Binder environments and check the result by the end of the workshop. For this purpose, it’s recommended to have data and R code ready, ideally in a GitHub repository.&lt;/p>
&lt;/div>
&lt;div id="improving-data-dashboards" class="section level5">
&lt;h5>Improving data dashboards&lt;/h5>
&lt;p>We will practise how to improve the functionality of dashboards using some HTML, CSS and Javascript code, which is &lt;a href="https://www.w3schools.com/whatis/">the basis of websites&lt;/a>.&lt;/p>
&lt;pre>&lt;code>&amp;lt;!-- Javascript function to enable a hovering tooltip --&amp;gt;
&amp;lt;script&amp;gt;
$(document).ready(function(){
$(&amp;#39;[data-toggle=&amp;quot;tooltip1&amp;quot;]&amp;#39;).tooltip();
});
&amp;lt;/script&amp;gt;&lt;/code>&lt;/pre>
&lt;p align="center">
&lt;a href = 'https://shiny.rstudio.com/gallery/'> &lt;img align = 'center' width = '60%' src = 'https://raw.githubusercontent.com/pablobernabeu/data-is-present/master/dashboard%20gif.gif' alt = 'Examples of data dashboards' /> &lt;/a>
&lt;/p>
&lt;/div>
&lt;div id="trade-offs-among-dashboards" class="section level5">
&lt;h5>Trade-offs among dashboards&lt;/h5>
&lt;p>Next, we will practise with three dashboard types—&lt;a href="https://rmarkdown.rstudio.com/flexdashboard/using.html">Flexdashboard&lt;/a>, &lt;a href="https://shiny.rstudio.com/tutorial/">Shiny&lt;/a> and &lt;a href="https://rmarkdown.rstudio.com/flexdashboard/shiny.html">Flexdashboard-Shiny&lt;/a>—and with the suitable hosting platforms. Firstly, the strength of Flexdashboard (&lt;a href="http://rpubs.com/pcbernabeu/Dutch-modality-exclusivity-norms">example&lt;/a>) is its basis on R Markdown, yielding an unmatched user interface (&lt;em>front-end&lt;/em>). Secondly, the strength of Shiny (&lt;a href="https://pablobernabeu.shinyapps.io/ERP-waveform-visualization_CMS-experiment/">example&lt;/a>) is the input reactivity (&lt;em>back-end&lt;/em>) it offers, allowing users to download sections of data they select, in various formats. Last, Flexdashboard-Shiny (&lt;a href="https://pablobernabeu.shinyapps.io/dutch-modality-exclusivity-norms/">example&lt;/a>) combines the best of both worlds.&lt;/p>
&lt;p align="center">
★ &lt;b> Flexdashboard &lt;/b> ★
&lt;/p>
&lt;p align="center">
★ ★ &lt;b> Shiny &lt;/b> ★ ★
&lt;/p>
&lt;p align="center">
★ ★ ★ &lt;b> Flexdashboard-Shiny &lt;/b> ★ ★ ★
&lt;/p>
&lt;p>Flexdashboard types are rendered as an HTML document—simple websites—, and can therefore be easily published on personal sites or &lt;a href="https://rpubs.com/">RPubs&lt;/a>. This is convenient because no special hosting is required. In contrast, Shiny and Flexdashboard-Shiny types offer greater features, but require Shiny servers. Fortunately, the shinyapps.io server is available for free, up to some &lt;a href="https://www.shinyapps.io/">usage limit&lt;/a>. This server can host any of the three dashboards mentioned here. Another good option is presented by Binder environments, which can host the Shiny-type dashboards with no (explicit) limit. Yet, the Flexdashboard-Shiny type cannot be hosted in this server (&lt;a href="https://github.com/jupyter/repo2docker/issues/799">as of January 2020, at least&lt;/a>). Consequently, greater functionality may come at a cost for dashboards that have any considerable traffic, whereas dashboards with low traffic may do well on shinyapps.io. Knowing these trade-offs can help navigate &lt;a href="https://support.rstudio.com/hc/en-us/articles/217592947-What-are-the-limits-of-the-shinyapps-io-Free-plan-">usage limits&lt;/a>, save on web hosting fees, and increase the availability of our dashboards online, as we can offer fall-back versions on different platforms, as in the example below:&lt;/p>
&lt;blockquote>
&lt;p>… &lt;em>&lt;a href="https://pablobernabeu.shinyapps.io/dutch-modality-exclusivity-norms/">preferred-dashboard&lt;/a> (in case of downtime, please visit this &lt;a href="http://rpubs.com/pcbernabeu/Dutch-modality-exclusivity-norms">alternative&lt;/a>)&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;p>Transforming dashboards into the different versions can be as easy as enabling or disabling some features, especially input reactivity. For instance, if we want to downgrade a Flexdashboard-Shiny to a Flexdashboard, to publish it outside of a Shiny server (see &lt;a href="https://github.com/pablobernabeu/Modality-exclusivity-norms-Bernabeu-et-al/blob/master/Dutch-modality-exclusivity-norms-RPubs.Rmd">example&lt;/a>), we must delete &lt;code>runtime:shiny&lt;/code> from the header, and disable reactive features, as below.&lt;/p>
&lt;pre>&lt;code>
``` r
# Number of words selected on sidebar
# reactive(cat(paste0(&amp;#39;Words selected below: &amp;#39;, nrow(selected_props()))))
```&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="free-accounts-and-tips" class="section level5">
&lt;h5>Free accounts and tips&lt;/h5>
&lt;p>Hosting sites have specific terms of use. For instance, &lt;a href="https://www.shinyapps.io/">shinyapps.io&lt;/a> has a free starter license with limited use. Free apps can handle a large but limited amount of data, and up to five apps may be created. Beyond this, RStudio offers a wide range of subscriptions starting at $9/month.&lt;/p>
&lt;p>Memory and traffic limits of the free shinyapps.io account can sometimes present problems when heavy data data sets are used, or there are many visits to the app. The memory overload issue is often flagged as &lt;code>Shiny cannot use on-disk bookmarking&lt;/code>, whereas excessive traffic may see the app not loading. Fortunately, usage limits need not always require a paid subscription or a &lt;a href="https://www.r-bloggers.com/alternative-approaches-to-scaling-shiny-with-rstudio-shiny-server-shinyproxy-or-custom-architecture/">custom server&lt;/a>, thanks to the following workarounds:&lt;/p>
&lt;ul>
&lt;li>develop app locally as far as possible, and only deploy to shinyapps.io only at the last stage;&lt;/li>
&lt;li>prune data set, leaving only the necessary data;&lt;/li>
&lt;li>if necessary, unlink data by splitting it into different sets, reducing computational demands;&lt;/li>
&lt;li>if necessary, use various apps (five are allowed in each free shinyapps.io account);&lt;/li>
&lt;li>if necessary, link from the app to a PDF with visualisations requiring heavy, interlinked data. High-resolution plots can be rendered into a PDF document in a snap, using code such as below.&lt;/li>
&lt;/ul>
&lt;pre>&lt;code>pdf(&amp;#39;List of plots per page&amp;#39;, width = 13, height = 5)
print(plot1)
print(plot2)
# ...
print(plot150)
dev.off()&lt;/code>&lt;/pre>
&lt;p>Conveniently, all text in a PDF—even in plots—is indexed, so it can be searched [ Ctrl+f / Cmd+f / 🔍 ] (see &lt;a href="https://osf.io/2tpxn/">example&lt;/a>). Furthermore, you may also &lt;a href="http://www.ilovepdf.com/">merge the rendered PDF with any other documents&lt;/a>.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="prerequisites-and-suggestions-for-participation-in-each-workshop" class="section level4">
&lt;h4>Prerequisites and suggestions for participation in each workshop&lt;/h4>
&lt;p>&lt;em>Necessary:&lt;/em> laptop or computer with &lt;a href="https://www.r-project.org/">R&lt;/a> and &lt;a href="https://rstudio.com/products/rstudio/download/">RStudio&lt;/a> installed, or access to &lt;a href="https://rstudio.cloud/">RStudio Cloud&lt;/a>; familiarity with the content of the preceding workshops through the web links herein.&lt;/p>
&lt;p>&lt;em>Suggested:&lt;/em> having your own data and R code ready (on a Github repository if participating in Workshop 4); participation in some of the preceding workshops.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="datathons-creating-reproducible-documents-and-dashboards" class="section level3">
&lt;h3>Datathons: creating reproducible documents and dashboards&lt;/h3>
&lt;p>In these coding meetups, participants collaborate to create reproducible documents or dashboards using the data and software they prefer (see &lt;a href="https://github.com/pablobernabeu/Data-is-present/tree/master/examples-documents-dashboards">examples&lt;/a>). Since the work can be split across different people and sections, some nice products may be achieved within a session. Any programming languages may be used.&lt;/p>
&lt;ul>
&lt;li>&lt;p>&lt;strong>Data used:&lt;/strong> academic or non-academic data of your own or from open-access sources such as &lt;a href="https://osf.io">OSF&lt;/a>, scientific journals, governments, international institutions, NGOs, etc.&lt;/p>
&lt;ul>
&lt;li>Inspired by the great &lt;a href="https://reprohack.github.io/reprohack-hq/">Reprohacks&lt;/a>, content suggestions are encouraged. That is, if you’d like to have a reproducible document or dashboard created for a certain, open-access data set, please let us know, and some participants may take it on. Suggestions may be posted as &lt;a href="https://github.com/pablobernabeu/Data-is-present/issues">issues&lt;/a> or emailed to &lt;a href="mailto:p.bernabeu@lancaster.ac.uk" class="email">p.bernabeu@lancaster.ac.uk&lt;/a>.
&lt;br>&lt;/br>&lt;/li>
&lt;/ul>&lt;/li>
&lt;li>&lt;p>&lt;strong>Purposes&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>&lt;p>collaborating to visualise data in novel ways using reproducible documents or interactive dashboards. For this purpose, participants sometimes draw on additional data to look at a bigger picture;&lt;/p>&lt;/li>
&lt;li>&lt;p>reflecting on the process by reviewing the techniques applied and challenges encountered.&lt;/p>&lt;/li>
&lt;/ul>&lt;/li>
&lt;li>&lt;p>&lt;strong>Output:&lt;/strong> A key aspect of datathons is the creation of output. Documents and dashboards are (co-)authored by the participants who work on them, who can then publish them on their websites, or on &lt;a href="https://rpubs.com/">RPubs&lt;/a>, &lt;a href="https://mybinder.org/">Binder&lt;/a>, &lt;a href="https://www.shinyapps.io/">Shinyapps&lt;/a> or &lt;a href="https://rstudio.com/products/shiny/shiny-server/">custom servers&lt;/a>. Time constraints notwithstanding, a lot of this output may be very enticing for further development by the same participants, or even by other people if the code is shared online. Just like with data, an attribution licence can be attached to the code.&lt;/p>&lt;/li>
&lt;/ul>
&lt;div id="prerequisites-and-suggestions-for-participation-in-datathons" class="section level4">
&lt;h4>Prerequisites and suggestions for participation in datathons&lt;/h4>
&lt;p>&lt;em>Necessary:&lt;/em> basic knowledge of reproducible documents or dashboards.&lt;/p>
&lt;p>&lt;em>Suggested:&lt;/em> familiarity with the development of reproducible documents or dashboards; an idea about the data you’d like to work with and the kind of document or dashboard you want to create.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="contact" class="section level2">
&lt;h2>Contact&lt;/h2>
&lt;p>Please submit any queries or requests by &lt;a href="https://github.com/pablobernabeu/Data-is-present/issues">posting an issue&lt;/a> or emailing &lt;a href="mailto:p.bernabeu@lancaster.ac.uk" class="email">p.bernabeu@lancaster.ac.uk&lt;/a>.&lt;/p>
&lt;/div></description><category>s</category><category>programming</category><category>education</category><category>workshop</category><category>datathon</category><category>data presentation</category><category>data visualisation</category><category>dashboard</category><category>reproducibility</category><category>open science</category><category>open data</category><category>statistics</category><category>R</category><category>R Shiny</category><category>Flexdashboard</category><category>HTML</category><category>CSS</category><category>Software Sustainability Institute Fellowship</category><category>education</category><category>programming</category><category>R</category></item><item><title>Dutch modality exclusivity norms</title><link>https://pablobernabeu.github.io/applications-and-dashboards/bernabeu-2018-modalitynorms/</link><pubDate>Mon, 01 Jan 2018 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/applications-and-dashboards/bernabeu-2018-modalitynorms/</guid><description>&lt;a href='https://pablobernabeu.shinyapps.io/Dutch-modality-exclusivity-norms'>
&lt;button style = "background-color: white; color: black; border: 2px solid #196F27; border-radius: 12px;">
&lt;h3 style = "margin-top: 7px !important; margin-left: 9px !important; margin-right: 9px !important;">
&lt;span style="color:#DBE6DA;">&lt;/span> Complete web application &lt;font style='font-size:60%;'>&lt;i>Flexdashboard-Shiny&lt;/i>&lt;/font> &lt;/h3>&lt;/button>&lt;/a>
&lt;br>
&lt;br>
&lt;a href='https://pablobernabeu.github.io/dashboards/Dutch-modality-exclusivity-norms'>
&lt;button style = "background-color: white; color: black; border: 2px solid #4CAF50; border-radius: 12px;">
&lt;h3 style = "margin-top: 7px !important; margin-left: 9px !important; margin-right: 9px !important;">
&lt;span style="color:#DBE6DA;">&lt;/span> Reduced dashboard &lt;font style='font-size:60%;'>&lt;i>Flexdashboard&lt;/i>&lt;/font> &lt;/h3>&lt;/button>&lt;/a> &amp;nbsp;
&lt;br>
&lt;br>
&lt;h3 id="how-it-works">How it works&lt;/h3>
&lt;p>&lt;div class="mermaid">
graph TD
A["Dutch modality&lt;br/>exclusivity norms data"] --> B["Flexdashboard front-end&lt;br/>(R Markdown)"]
B --> C["Shiny back-end&lt;br/>(reactive selection and download)"]
C --> D["Info tab: HTML and CSS text&lt;br/>plus rmarkdown output"]
C --> E["Table tab: reactable&lt;br/>(colours, bar charts)"]
C --> F["Plot tab: plotly&lt;br/>(PCA scatter, tooltips)"]
B --> G["Static Flexdashboard-only version&lt;br/>on RPubs (Shiny removed)"]
&lt;/div>
This web application presents linguistic data over several tabs. The code combines the great front-end of Flexdashboard—based on R Markdown and yielding an unmatched user interface—, with the great back-end of Shiny—allowing users to download sections of data they select, in various formats.&lt;/p>
&lt;ul>
&lt;li>
&lt;p>A nice find was the 'reactable' package, which implements Javascript under the hood to allow the use of colours, bar charts, etc.&lt;/p>
&lt;pre>&lt;code>Auditory = colDef(header = with_tooltip('Auditory Rating',
'Mean rating of each word on the auditory modality across participants.'),
cell = function(value) {
width &amp;lt;- paste0(value / max(table_data$Auditory) * 100, &amp;quot;%&amp;quot;)
value = sprintf(&amp;quot;%.2f&amp;quot;, round(value,2)) # Round to two digits, keeping trailing zeros
bar_chart(value, width = width, fill = '#ff3030')
},
align = 'left'),
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>One of the hardest nuts to crack was allowing the full functionality of tables—i.e., scaling to screen, frozen header, and vertical and horizontal scrolling—whilst having tweaked the vertical/horizontal orientation of the dashboard sections. Initial clashes were resolved by adjusting the section's CSS styles&lt;/p>
&lt;pre>&lt;code>Table {#table style=&amp;quot;background-color:#FCFCFC;&amp;quot;}
=======================================================================
Inputs {.sidebar style='position:fixed; padding-top: 65px; padding-bottom:30px;'}
-----------------------------------------------------------------------
&lt;/code>&lt;/pre>
&lt;p>and by also adjusting the reactable settings.&lt;/p>
&lt;pre>&lt;code>renderReactable({
reactable(selected_words(),
defaultSorted = list(cat = 'desc', word = 'asc'),
defaultColDef = colDef(footerStyle = list(fontWeight = &amp;quot;bold&amp;quot;)),
height = 840, striped = TRUE, pagination = FALSE, highlight = TRUE,
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>A nice feature, especially suited to Flexdashboard, was the use of different formats across tabs. Whereas the Info tab presents long text using HTML and CSS styling, along with rmarkdown code output, the other tabs rely more strongly on Javascript features, enabled by R packages such as ‘shiny’ and sweetalert (e.g., allowing modal dialogs—pop-ups), reactable and plotly (e.g., allowing information opened by hovering—tooltips).&lt;/p>
&lt;pre>&lt;code>```{r}
# reactive for the word bar
highlighted_properties = reactive(input$highlighted_properties)
renderPlotly({
ggplotly(
ggplot( selected_props(), aes(RC1, RC2, label = as.character(word), color = main,
# Html tags below used for format. Decimals rounded to two.
text = paste0(' ', '&amp;lt;span style=&amp;quot;padding-top:3px; padding-bottom:3px; font-size:2.2em; color:#EEEEEE&amp;quot;&amp;gt;', capitalize(word), '&amp;lt;/span&amp;gt; ', '&amp;lt;br&amp;gt;',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Dominant modality: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', main, ' ',
' ', '&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Modality exclusivity: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', sprintf(&amp;quot;%.2f&amp;quot;, round(Exclusivity, 2)), '% ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Perceptual strength: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', sprintf(&amp;quot;%.2f&amp;quot;, round(Perceptualstrength, 2)),
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Auditory rating: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', sprintf(&amp;quot;%.2f&amp;quot;, round(Auditory, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Haptic rating: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', sprintf(&amp;quot;%.2f&amp;quot;, round(Haptic, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Visual rating: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', sprintf(&amp;quot;%.2f&amp;quot;, round(Visual, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Concreteness (Brysbaert et al., 2014): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
sprintf(&amp;quot;%.2f&amp;quot;, round(concrete_Brysbaertetal2014, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Number of letters: &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;', letters, ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Number of phonemes (DutchPOND): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
round(phonemes_DUTCHPOND, 2), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Contextual diversity (lg10CD SUBTLEX-NL): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
sprintf(&amp;quot;%.2f&amp;quot;, round(freq_lg10CD_SUBTLEXNL, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Word frequency (lg10WF SUBTLEX-NL): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
sprintf(&amp;quot;%.2f&amp;quot;, round(freq_lg10WF_SUBTLEXNL, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Lemma frequency (CELEX): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
sprintf(&amp;quot;%.2f&amp;quot;, round(freq_CELEX_lem, 2)), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Phonological neighbourhood size (DutchPOND): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
round(phon_neighbours_DUTCHPOND, 2), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Orthographic neighbourhood size (DutchPOND): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
round(orth_neighbours_DUTCHPOND, 2), ' ',
'&amp;lt;/b&amp;gt;&amp;lt;br&amp;gt;&amp;lt;span style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt; Age of acquisition (Brysbaert et al., 2014): &amp;lt;/span&amp;gt;&amp;lt;b style=&amp;quot;color:#EEEEEE&amp;quot;&amp;gt;',
sprintf(&amp;quot;%.2f&amp;quot;, round(AoA_Brysbaertetal2014, 2)), ' ', '&amp;lt;br&amp;gt; '
) ) ) +
geom_text(size = ifelse(selected_props()$word %in% highlighted_properties(), 7,
ifelse(is.null(highlighted_properties()), 3, 2.8)),
fontface = ifelse(selected_props()$word %in% highlighted_properties(), 'bold', 'plain')) +
geom_point(alpha = 0) + # This geom_point helps to colour the tooltip according to the dominant modality
scale_colour_manual(values = colours, drop = FALSE) + theme_bw() + ggtitle('Property words') +
labs(x = 'Varimax-rotated Principal Component 1', y = 'Varimax-rotated Principal Component 2') +
guides(color = guide_legend(title = 'Main&amp;lt;br&amp;gt;modality')) +
theme( plot.background = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), panel.border = element_blank(),
axis.line = element_line(color = 'black'), plot.title = element_text(size = 14, hjust = .5),
axis.title.x = element_text(colour = 'black', size = 12, margin = margin(15,15,0,15)),
axis.title.y = element_text(colour = 'black', size = 12, margin = margin(0,15,15,5)),
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8),
legend.background = element_rect(size = 2), legend.position = 'none',
legend.title = element_blank(),
legend.text = element_text(colour = colours, size = 13) ),
tooltip = 'text'
)
})
# For download, save plot without the interactive 'plotly' part
properties_png = reactive({ ggplot(selected_props(), aes(RC1, RC2, color = main, label = as.character(word))) +
geom_text(show.legend = FALSE, size = ifelse(selected_props()$word %in% highlighted_properties(), 7,
ifelse(is.null(highlighted_properties()), 3, 2.8)),
fontface = ifelse(selected_props()$word %in% highlighted_properties(), 'bold', 'plain')) +
geom_point(alpha = 0) + scale_colour_manual(values = colours, drop = FALSE) + theme_bw() +
guides(color = guide_legend(title = 'Main&amp;lt;br&amp;gt;modality', override.aes = list(size = 7, alpha = 1))) +
ggtitle( paste0('Properties', ' (showing ', nrow(selected_props()), ' out of ', nrow(props), ')') ) +
labs(x = 'Varimax-rotated Principal Component 1', y = 'Varimax-rotated Principal Component 2') +
theme( plot.background = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), panel.border = element_blank(),
axis.line = element_line(color = 'black'), plot.title = element_text(size = 17, hjust = .5, margin = margin(3,3,7,3)),
axis.title.x = element_text(colour = 'black', size = 12, margin = margin(10,10,2,10)),
axis.title.y = element_text(colour = 'black', size = 12, margin = margin(10,10,10,5)),
axis.text.x = element_text(size = 8), axis.text.y = element_text(size = 8),
legend.background = element_rect(size = 2), legend.position = 'right',
legend.title = element_blank(), legend.text = element_text(size = 15))
})
```
&lt;/code>&lt;/pre>
&lt;p>The only instance in which I drew on JavaScript code outside R packages was to enable tooltips beyond the packages’ limits—for instance, in the sidebar. This JavaScript feature is created at the top of the script, in the head area.&lt;/p>
&lt;pre>&lt;code>&amp;lt;!-- Javascript function to enable a hovering tooltip --&amp;gt;
&amp;lt;script&amp;gt;
$(document).ready(function(){
$('[data-toggle=&amp;quot;tooltip1&amp;quot;]').tooltip();
});
&amp;lt;/script&amp;gt;
&lt;/code>&lt;/pre>
&lt;/li>
&lt;li>
&lt;p>In the sidebar, I added a reactive mean for each variable, complementing the range selector.&lt;/p>
&lt;pre>&lt;code>reactive(cat(paste0('Mean = ',
sprintf(&amp;quot;%.2f&amp;quot;, round(mean(selected_words()$Exclusivity),2)))))
&lt;/code>&lt;/pre>
&lt;/li>
&lt;/ul>
&lt;h2 id="static-version-published-on-rpubs">Static version published on RPubs&lt;/h2>
&lt;p>A reduced,
&lt;a href="https://rpubs.com/pcbernabeu/Dutch-modality-exclusivity-norms">&lt;em>static&lt;/em> version&lt;/a> was also created to increase the availability of the content. Removing some reactivity features allows the dashboard to be published as a standard website (i.e., on a personal website, on
&lt;a href="https://rpubs.com/">RPubs&lt;/a>, etc.), without the need for a back-end Shiny server. Note that this type of website is dubbed 'static', but it can retain multiple interactive features thanks to Javascript-based tools under the hood, allowed by R packages such as &lt;code>leaflet&lt;/code> for maps, &lt;code>DT&lt;/code> for tables, &lt;code>plotly&lt;/code> for plots, etc.&lt;/p>
&lt;p>To create the Flexdashboard-only version departing from the Flexdashboard-Shiny version, I deleted &lt;code>runtime: shiny&lt;/code> from the YAML header, and disabled Shiny reactive inputs and objects, as below.&lt;/p>
&lt;pre>&lt;code>```{r}
# Number of words selected on sidebar
# reactive(cat(paste0('Words selected below: ', nrow(selected_props()))))
```
&lt;/code>&lt;/pre>
&lt;h2 id="reference">Reference&lt;/h2>
&lt;p>Bernabeu, P. (2018). Dutch modality exclusivity norms for 336 properties and 411 concepts [Web application]. Retrieved from &lt;a href="https://pablobernabeu.shinyapps.io/Dutch-Modality-Exclusivity-Norms">https://pablobernabeu.shinyapps.io/Dutch-Modality-Exclusivity-Norms&lt;/a>&lt;/p></description><category>web application</category><category>data dashboard</category><category>Flexdashboard</category><category>R</category><category>R Shiny</category><category>statistics</category><category>regression</category><category>principal component analysis</category><category>modality exclusivity norms</category><category>Dutch</category><category>linguistics</category><category>HTML</category><category>CSS</category><category>web application</category><category>research and teaching applications</category><category>R</category></item><item><title>Naive principal component analysis in R</title><link>https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/</link><pubDate>Mon, 01 Jan 2018 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/</guid><description>
&lt;p>&lt;a href="https://en.wikipedia.org/wiki/Principal_component_analysis">Principal Component Analysis (PCA)&lt;/a> is a technique used to find the core components that underlie different variables. It comes in very useful whenever doubts arise about the true origin of three or more variables. There are two main methods for performing a PCA: naive or less naive. In the naive method, you first check some conditions in your data which will determine the essentials of the analysis. In the less-naive method, you set those yourself based on whatever prior information or purposes you had. The latter method is appropriate when you already have enough information about the intercorrelations, or when you are required to select a specific number of components. I will tackle the naive method, mainly by following the guidelines in &lt;a href="https://freethegeogbooks.files.wordpress.com/2016/08/book-for-r-language-stats.pdf">Field, Miles, and Field (2012)&lt;/a>, with updated code where necessary. A &lt;a href="https://freethegeogbooks.files.wordpress.com/2016/08/book-for-r-language-stats.pdf">manual by Charles M. Friel&lt;/a> (Sam Houston State University) was also useful.&lt;/p>
&lt;p>The ‘naive’ approach is characterized by a first stage that checks whether the PCA should actually be performed with your current variables, or if some should be removed. The variables that are accepted are taken to a second stage which identifies the number of principal components that seem to underlie your set of variables.&lt;/p>
&lt;div id="stage-1.-determine-whether-pca-is-appropriate-at-all-considering-the-variables" class="section level2">
&lt;h2>STAGE 1. Determine whether PCA is appropriate at all, considering the variables&lt;/h2>
&lt;p>&lt;img alt="Lower-triangular correlation matrix for variables Q01 to Q07, with several coefficients circled in orange" style = "float: right; margin-left: 30px;" width = "45%" src="https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/1.jpg" />&lt;/p>
&lt;ul>
&lt;li>&lt;p>Variables should be &lt;strong>inter-correlated enough but not too much.&lt;/strong> Field et al. (2012) provide some thresholds, suggesting that no variable should have many correlations below .30, or &lt;em>any&lt;/em> correlation at all above .90. Thus, in the example here, variable Q06 should probably be excluded from the PCA.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>Bartlett’s test&lt;/strong>, on the nature of the intercorrelations, should be significant. Significance suggests that the variables are not an ‘identity matrix’ in which correlations are a sampling error.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>KMO&lt;/strong> (Kaiser-Meyer-Olkin), a measure of sampling adequacy based on common variance (so similar purpose as Bartlett’s). As Field et al. review, ‘values between .5 and .7 are mediocre, values between .7 and .8 are good, values between .8 and .9 are great and values above .9 are superb’ (p. 761). There’s a general score as well as one per variable. The general one will often be good, whereas the individual scores may more likely fail. Any variable with a score below .5 should probably be removed, and the test should be run again.&lt;/p>&lt;/li>
&lt;li>&lt;p>&lt;strong>Determinant:&lt;/strong> A formula about multicollinearity. The result should preferably fall below .00001.
Note that some of these tests are run on the dataframe and others on a correlation matrix of the data, as distinguished below.&lt;/p>
&lt;pre>&lt;code># Necessary libraries
library(ltm)
library(lattice)
library(psych)
library(car)
library(pastecs)
library(scales)
library(ggplot2)
library(arules)
library(plyr)
library(Rmisc)
library(GPArotation)
library(gdata)
library(MASS)
library(qpcR)
library(dplyr)
library(gtools)
library(Hmisc)
# Select variables of interest for the PCA
dataset = mydata[, c(&amp;#39;select_var1&amp;#39;, &amp;#39;select_var1&amp;#39;,
&amp;#39;select_var2&amp;#39;, &amp;#39;select_var3&amp;#39;, &amp;#39;select_var4&amp;#39;,
&amp;#39;select_var5&amp;#39;, &amp;#39;select_var6&amp;#39;, &amp;#39;select_var7&amp;#39;)]
# Create matrix: some tests will require it
data_matrix = cor(dataset, use = &amp;#39;complete.obs&amp;#39;)
# See intercorrelations
round(data_matrix, 2)
# Bartlett&amp;#39;s
cortest.bartlett(dataset)
# KMO (Kaiser-Meyer-Olkin)
KMO(data_matrix)
# Determinant
det(data_matrix)&lt;/code>&lt;/pre>&lt;/li>
&lt;/ul>
&lt;/div>
&lt;div id="stage-2.-identify-number-of-components-aka-factors" class="section level2">
&lt;h2>STAGE 2. Identify number of components (aka factors)&lt;/h2>
&lt;p>In this stage, principal components (formally called ‘factors’ at this stage) are identified among the set of variables.&lt;/p>
&lt;ul>
&lt;li>&lt;p>The identification is done through a basic, ‘unrotated’ PCA. The number of components set a priori must equal the number of variables that are being tested.&lt;/p>
&lt;pre>&lt;code># Start off with unrotated PCA
pc1 = psych::principal(dataset, nfactors = length(dataset), rotate=&amp;quot;none&amp;quot;)
pc1&lt;/code>&lt;/pre>
&lt;p>Below is an example result:&lt;/p>
&lt;pre>&lt;code> ## Principal Components Analysis
## Call: psych::principal(r = eng_prop, nfactors = 3, rotate = &amp;quot;none&amp;quot;)
## Standardized loadings (pattern matrix) based upon correlation matrix
## PC1 PC2 PC3 h2 u2 com
## Aud_eng -0.89 0.13 0.44 1 -2.2e-16 1.5
## Hap_eng 0.64 0.75 0.15 1 1.1e-16 2.0
## Vis_eng 0.81 -0.46 0.36 1 -4.4e-16 2.0
##
## PC1 PC2 PC3
## SS loadings 1.87 0.79 0.34
## Proportion Var 0.62 0.26 0.11
## Cumulative Var 0.62 0.89 1.00
## Proportion Explained 0.62 0.26 0.11
## Cumulative Proportion 0.62 0.89 1.00
##
## Mean item complexity = 1.9
## Test of the hypothesis that 3 components are sufficient.
##
## The root mean square of the residuals (RMSR) is 0
## with the empirical chi square 0 with prob &amp;lt; NA
##
## Fit based upon off diagonal values = 1&lt;/code>&lt;/pre>&lt;/li>
&lt;/ul>
&lt;p>Among the columns, there are first the correlations between variables and components, followed by a column (h2) with the &lt;strong>‘communalities’&lt;/strong>. If less factors than variables had been selected, communality values would be below 1. Then there is the uniqueness column (u2): &lt;strong>uniqueness&lt;/strong> is equal to 1 minus the communality. Next is ‘com’, which reflects the &lt;strong>complexity&lt;/strong> with which a variable relates to the principal components. Those components are precisely found below. The first row contains the sums of squared loadings, or eigenvalues, namely, the total variance explained by each linear component. This value corresponds to the number of units explained out of all possible factors (which were three in the above example). The rows below all cut from the same cloth. &lt;em>Proportion var&lt;/em> = variance explained over a total of 1. This is the result of dividing the eigenvalue by the number of components. Multiply by 100 and you get the percentage of total variance explained, which becomes useful. In the example, 99% of the variance has been explained. Aside from the meddling maths, we should actually expect 100% there because the number of factors equaled the number of variables. &lt;em>Cumulative var:&lt;/em> variance added consecutively up to the last component. &lt;em>Proportion explained:&lt;/em> variance explained over what has actually been explained (only when variables = factors is this the same as Proportion var). &lt;em>Cumulative proportion:&lt;/em> the actually explained variance added consecutively up to the last component (Field et al., 2012).&lt;/p>
&lt;p>According to Field et al. (2012), two criteria can be used to determine the number of components that should be carried forward to the next stage:&lt;/p>
&lt;ul>
&lt;li>&lt;p>SS (sum of squares) loadings, with two possible cut-off points. On the one hand, following Kaiser’s threshold, we should select components with SS loadings &amp;gt; 1. In the example result shown above, only PC1 meets this criterion. A more lenient alternative is Kaiser’s threshold, whereby SS loadings &amp;gt; .7 are accepted. In the example result above, PC2 meet this criterion too.&lt;/p>&lt;/li>
&lt;li>&lt;p>Scree plot: retain as many components as the number of points after the point of inflection. To create a scree plot, call:&lt;/p>
&lt;pre>&lt;code>plot(pc1$values, type = &amp;#39;b&amp;#39;)&lt;/code>&lt;/pre>&lt;/li>
&lt;/ul>
&lt;p>&lt;img alt="Scree plot of PCA eigenvalues against component number, dropping steeply then bending after the first component" style = "float: right; margin-left: 30px;" width = "35%" src="https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/2.jpg" />&lt;/p>
&lt;p>Imagine a straight line &lt;strong>from the first point on the right.&lt;/strong> Once this line bends considerably, count the points after the bend and up to the last point on the left. The number of points is the number of components to select. The example here is probably the most complicated (two components were finally chosen), but often it’s easier &lt;a href="https://www.google.nl/search?sca_esv=582945116&amp;amp;q=select+principal+components+scree+plot+point+inflection&amp;amp;tbm=isch">see examples&lt;/a>.&lt;/p>
&lt;p>Based on either or both criteria, select the definitive number of components.&lt;/p>
&lt;/div>
&lt;div id="stage-3.-run-definitive-pca" class="section level2">
&lt;h2>STAGE 3. Run definitive PCA&lt;/h2>
&lt;p>Run a very similar command as you did before, but now with a more advanced method. The first PCA, a heuristic one, worked essentially on the inter-correlations. The definitive PCA, in contrast, will implement a prior shuffling known as ‘rotation’, to ensure that the result is robust enough (just like cards are shuffled). Explained variance is captured better this way. The go-to rotation method is the orthogonal, or ‘varimax’ (though others may be considered too).&lt;/p>
&lt;pre>&lt;code># Now with varimax rotation, Kaiser-normalized by default:
pc2 = psych::principal(dataset, nfactors=2, rotate = &amp;quot;varimax&amp;quot;,
scores = TRUE)
pc2
pc2$loadings
# Sanity check
pc2$residual
pc2$fit
pc2$communality&lt;/code>&lt;/pre>
&lt;p>According to Field et al. (2012), we would want:&lt;/p>
&lt;ul>
&lt;li>Less than half of &lt;strong>residuals&lt;/strong> with absolute values &amp;gt; 0.05&lt;/li>
&lt;li>Model &lt;strong>fit&lt;/strong> &amp;gt; .9&lt;/li>
&lt;li>All &lt;strong>communalities&lt;/strong> &amp;gt; .7&lt;/li>
&lt;/ul>
&lt;p>If any of this fails, consider changing the number of factors. Next, the rotated components that have been ‘extracted’ from the core of the set of variables can be added to the dataset. This would enable the use of these components as new variables that might prove powerful and useful (as in &lt;a href="http://onlinelibrary.wiley.com/doi/10.1111/j.1551-6709.2010.01157.x/full">this research&lt;/a>).&lt;/p>
&lt;pre>&lt;code>dataset = cbind(dataset, pc2$scores)
summary(dataset$RC1, dataset$RC2)&lt;/code>&lt;/pre>
&lt;/div>
&lt;div id="stage-4.-determine-ascription-of-each-variable-to-components" class="section level2">
&lt;h2>STAGE 4. Determine ascription of each variable to components&lt;/h2>
&lt;p>&lt;img alt="Loadings table for English and Dutch norms showing auditory, haptic and visual modalities on rotated components RC1 and RC2" style = "float: right; margin-left: 30px;" width = "55%" src="https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/3.jpg" />&lt;/p>
&lt;p>Check the main summary by just calling pc2, and see how each variable correlates with the rotated components. This is essential because it reveals how variables load on each component, or in other words, to which component a variable belongs. For instance, the table shown here belongs to a study about the meaning of words (Bernabeu, 2018). These results suggest that the visual and haptic modalities of words are quite related, whereas the auditory modality is relatively unique. When the analysis works out well, a cut-off point of &lt;em>r&lt;/em> = .8 may be applied for considering a variable as part of a component.&lt;/p>
&lt;/div>
&lt;div id="stage-5.-enjoy-the-plot" class="section level2">
&lt;h2>STAGE 5. Enjoy the plot&lt;/h2>
&lt;p>The plot is perhaps the coolest part about PCA. It really makes an awesome illustration of the power of data analysis.&lt;/p>
&lt;pre>&lt;code>ggplot(eng_props,
aes(RC1, RC2, label = as.character(main_eng))) + stat_density2d (color = &amp;quot;gray87&amp;quot;) +
geom_text(size = ifelse(eng_props$word_eng %in% w_set, 12, 7),
fontface = ifelse(eng_props$word_eng %in% w_set, &amp;#39;bold&amp;#39;, &amp;#39;plain&amp;#39;)) +
geom_point(data=eng_props[eng_props$word_eng %in% w_set,], pch=21, fill=NA, size=14, stroke=2, alpha=.6) +
labs(subtitle=&amp;#39;(Data from Lynott &amp;amp; Connell, 2009)&amp;#39;, x = &amp;quot;Varimax-rotated Principal Component 1&amp;quot;,
y = &amp;quot;Varimax-rotated Principal Component 2&amp;quot;) + theme_bw() +
theme( plot.background = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), panel.border = element_blank(),
axis.line = element_line(color = &amp;#39;black&amp;#39;),
axis.title.x = element_text(colour = &amp;#39;black&amp;#39;, size = 23, margin=margin(15,15,15,15)),
axis.title.y = element_text(colour = &amp;#39;black&amp;#39;, size = 23, margin=margin(15,15,15,15)),
axis.text.x = element_text(size=16), axis.text.y = element_text(size=16),
plot.title = element_text(hjust = 0.5, size = 32, face = &amp;quot;bold&amp;quot;, margin=margin(15,15,15,15)),
plot.subtitle = element_text(hjust = 0.5, size = 20, margin=margin(2,15,15,15)) ) +
geom_label_repel(data = eng_props[eng_props$word_eng %in% w_set,], aes(label = word_eng), size = 8,
alpha = 0.77, color = &amp;#39;black&amp;#39;, box.padding = 1.5 )&lt;/code>&lt;/pre>
&lt;p>Below is an example combining PCA plots with code similar to the above. These plots illustrate something further with regard to the relationships among modalities. In property words, the different modalities spread out more clearly than they do in concept words. This makes sense because in language, properties define concepts (Bernabeu, 2018).&lt;/p>
&lt;p>&lt;img alt="Four PCA scatter plots of words on rotated components: English and Dutch properties and concepts" src="https://pablobernabeu.github.io/2018/naive-principal-component-analysis-in-r/4.png" />&lt;/p>
&lt;p>An example of these analyses is &lt;a href="https://pablobernabeu.shinyapps.io/Dutch-modality-exclusivity-norms">available in available in this RStudio environment&lt;/a>, in the &lt;code>norms.R&lt;/code> script.&lt;/p>
&lt;/div>
&lt;div id="references" class="section level2">
&lt;h2>References&lt;/h2>
&lt;p>Bernabeu, P. (2018). &lt;em>Dutch modality exclusivity norms for 336 properties and 411 concepts&lt;/em>. PsyArXiv. &lt;a href="https://doi.org/10.31234/osf.io/s2c5h" class="uri">https://doi.org/10.31234/osf.io/s2c5h&lt;/a>&lt;/p>
&lt;p>Field, A. P., Miles, J., &amp;amp; Field, Z. (2012). &lt;em>Discovering Statistics Using R&lt;/em>. London, UK: Sage.&lt;/p>
&lt;/div></description><category>s</category><category>principal component analysis</category><category>statistics</category><category>dimensionality reduction</category><category>R</category><category>statistics</category><category>R</category></item><item><title>Modality switch effects emerge early and increase throughout conceptual processing</title><link>https://pablobernabeu.github.io/applications-and-dashboards/bernabeu-etal-2017-modalityswitch/</link><pubDate>Sun, 01 Jan 2017 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/applications-and-dashboards/bernabeu-etal-2017-modalityswitch/</guid><description>&lt;a href='https://pablobernabeu.shinyapps.io/ERP-waveform-visualization_CMS-experiment/'>
&lt;button style = "background-color: white; color: black; border: 2px solid #4CAF50; border-radius: 12px;">
&lt;h3 style = "margin-top: 7px !important; margin-left: 9px !important; margin-right: 9px !important;">
&lt;span style="color:#DBE6DA;">&lt;/span> Web application &lt;/h3>&lt;/button>&lt;/a> &amp;nbsp;
&lt;br>
&lt;br>
&lt;h3 id="how-it-works">How it works&lt;/h3>
&lt;div class="mermaid">
graph TD
A["EEG-ERP data from word&lt;br/>comprehension experiment"] --> B["ERP plots spanning 800 ms&lt;br/>of word processing"]
B --> C["Groups of participants"]
C --> D["Individual participants"]
D --> E["Brain areas"]
E --> F["Electrodes"]
B --> G["Download HD plots, view&lt;br/>95% confidence intervals"]
&lt;/div>
&lt;p>&lt;strong>Content&lt;/strong>&lt;/p>
&lt;p>The data are from a psychology experiment on the comprehension of words, in which electroencephalographic (EEG) responses were measured. The data are presented in plots spanning 800 milliseconds (the duration of word processing). The aim of this Shiny app is to facilitate the exploration of the data by researchers and the public. Users can delve into the different sections of the data. In a hierarchical order, these sections are groups of participants, individual participants, brain areas, and electrodes.&lt;/p>
&lt;p>&lt;strong>Shiny apps in science&lt;/strong>&lt;/p>
&lt;p>By creating this app, I tried to reach beyond the scope of current &lt;em>open science&lt;/em>, which is often confined to files shared on data repositories. I believe that Shiny apps will become general practice in science within a few years (
&lt;a href="http://www.research.lancs.ac.uk/portal/en/activities/presenting-data-interactively-online-using-r-shiny%28c9ce06ac-987e-4141-9121-016f6ee6d16b%29.html">see blog post or slides for more information&lt;/a>).&lt;/p>
&lt;p>&lt;strong>Technical details&lt;/strong>&lt;/p>
&lt;p>I used tabs on the upper area of the application page to avoid cramming the side bar with widgets. I adjusted the appearance of these tabs, and by means of 'reactivity' conditions, modified the inputs in the side bar depending on the active tab.&lt;/p>
&lt;pre>&lt;code>mainPanel(
tags$style(HTML('
.tabbable &amp;gt; .nav &amp;gt; li &amp;gt; a {background-color:white; color:#3E454E}
.tabbable &amp;gt; .nav &amp;gt; li &amp;gt; a:hover {background-color:#002555; color:white}
.tabbable &amp;gt; .nav &amp;gt; li[class=active] &amp;gt; a {background-color:#ECF4FF; color:black}
.tabbable &amp;gt; .nav &amp;gt; li[class=active] &amp;gt; a:hover {background-color:#E7F1FF; color:black}
')),
tabsetPanel(id='tabvals',
tabPanel(value=1, h4(strong('Group &amp;amp; Electrode')), br(), plotOutput('plot_GroupAndElectrode'),
h5(a(strong('See plots with 95% Confidence Intervals'), href='https://osf.io/2tpxn/',
target='_blank'), style='text-decoration: underline;'),
downloadButton('downloadPlot.1', 'Download HD plot'), br(), br(),
# EEG montage
img(src='https://preview.ibb.co/n7qiYR/EEG_montage.png', height=500, width=1000)),
tabPanel(value=2, h4(strong('Participant &amp;amp; Area')), br(), plotOutput('plot_ParticipantAndLocation'),
h5(a(strong('See plots with 95% Confidence Intervals'), href='https://osf.io/86ch9/',
target='_blank'), style='text-decoration: underline;'),
downloadButton('downloadPlot.2', 'Download HD plot'), br(), br(),
# EEG montage
img(src='https://preview.ibb.co/n7qiYR/EEG_montage.png', height=500, width=1000)),
tabPanel(value=3, h4(strong('Participant &amp;amp; Electrode')), br(), plotOutput('plot_ParticipantAndElectrode'),
br(), downloadButton('downloadPlot.3', 'Download HD plot'), br(), br(),
# EEG montage
img(src='https://preview.ibb.co/n7qiYR/EEG_montage.png', height=500, width=1000)),
tabPanel(value=4, h4(strong('OLD Group &amp;amp; Electrode')), br(), plotOutput('plot_OLDGroupAndElectrode'),
h5(a(strong('See plots with 95% Confidence Intervals'), href='https://osf.io/dvs2z/',
target='_blank'), style='text-decoration: underline;'),
downloadButton('downloadPlot.4', 'Download HD plot'), br(), br(),
# EEG montage
img(src='https://preview.ibb.co/n7qiYR/EEG_montage.png', height=500, width=1000))
),
&lt;/code>&lt;/pre>
&lt;p>The data set was fairly large, considering the fact that it's hosted with the free plan. In order to lighten the processing, I split the data into various files, reducing the total size. Furthermore, I outsourced a particularly heavy set of plots (those with Confidence Intervals) to PDF files, to which I linked in the app.&lt;/p>
&lt;pre>&lt;code>h5(a(strong('See plots with 95% Confidence Intervals'), href='https://osf.io/dvs2z/',
target='_blank'), style='text-decoration: underline;'),
&lt;/code>&lt;/pre>
&lt;p>I also used web links to the published paper and raw data, as well as to the &lt;em>server&lt;/em> and &lt;em>ui&lt;/em> scripts. These files, along with the data, are publicly available
&lt;a href="https://osf.io/97unm/">in this repository&lt;/a>; they may be accessed within the &amp;quot;Files&amp;quot; section, by opening the folders &amp;quot;ERPs&amp;quot; -&amp;gt; &amp;quot;Analyses of ERPs averaged across trials&amp;quot; -&amp;gt; &amp;quot;Shiny app&amp;quot;.&lt;/p>
&lt;p>Another feature I added was the download button.&lt;/p>
&lt;pre>&lt;code># From server.R script
spec_title = paste0('ERP waveforms for ', input$var.Group, ' Group, Electrode ', input$var.Electrodes.1, ' (negative values upward; time windows displayed)')
plot_GroupAndElectrode = ggplot(df2, aes(x=time, y=-microvolts, color=condition)) +
geom_rect(xmin=160, xmax=216, ymin=7.5, ymax=-8, color = 'grey75', fill='black', alpha=0, linetype='longdash') +
geom_rect(xmin=270, xmax=370, ymin=7.5, ymax=-8, color = 'grey75', fill='black', alpha=0, linetype='longdash') +
geom_rect(xmin=350, xmax=550, ymin=8, ymax=-7.5, color = 'grey75', fill='black', alpha=0, linetype='longdash') +
geom_rect(xmin=500, xmax=750, ymin=7.5, ymax=-8, color = 'grey75', fill='black', alpha=0, linetype='longdash') +
geom_line(size=1, alpha = 1) + scale_linetype_manual(values=colours) +
scale_y_continuous(limits=c(-8.38, 8.3), breaks=seq(-8,8,by=1), expand = c(0,0.1)) +
scale_x_continuous(limits=c(-208,808),breaks=seq(-200,800,by=100), expand = c(0.005,0), labels= c('-200','-100 ms','0','100 ms','200','300 ms','400','500 ms','600','700 ms','800')) +
ggtitle(spec_title) + theme_bw() + geom_vline(xintercept=0) +
annotate(geom='segment', y=seq(-8,8,1), yend=seq(-8,8,1), x=-4, xend=8, color='black') +
annotate(geom='segment', y=-8.2, yend=-8.38, x=seq(-200,800,100), xend=seq(-200,800,100), color='black') +
geom_segment(x = -200, y = 0, xend = 800, yend = 0, size=0.5, color='black') +
theme(legend.position = c(0.100, 0.150), legend.background = element_rect(fill='#EEEEEE', size=0),
axis.title=element_blank(), legend.key.width = unit(1.2,'cm'), legend.text=element_text(size=17),
legend.title = element_text(size=17, face='bold'), plot.title= element_text(size=20, hjust = 0.5, vjust=2),
axis.text.y = element_blank(), axis.text.x = element_text(size = 14, vjust= 2.12, face='bold', color = 'grey32', family='sans'),
axis.ticks=element_blank(), panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), plot.margin = unit(c(0.1,0.1,0,0), 'cm')) +
annotate('segment', x=160, xend=216, y=-8, yend=-8, colour = 'grey75', size = 1.5) +
annotate('segment', x=270, xend=370, y=-8, yend=-8, colour = 'grey75', size = 1.5) +
annotate('segment', x=350, xend=550, y=-7.5, yend=-7.5, colour = 'grey75', size = 1.5) +
annotate('segment', x=500, xend=750, y=-8, yend=-8, colour = 'grey75', size = 1.5) +
scale_fill_manual(name = 'Context / Target trial', values=colours) +
scale_color_manual(name = 'Context / Target trial', values=colours) +
guides(linetype=guide_legend(override.aes = list(size=1.2))) +
guides(color=guide_legend(override.aes = list(size=2.5))) +
# Print y axis labels within plot area:
annotate('text', label = expression(bold('\u2013' * '3 ' * '\u03bc' * 'V')), x = -29, y = 3, size = 4.5, color = 'grey32', family='sans') +
annotate('text', label = expression(bold('+3 ' * '\u03bc' * 'V')), x = -29, y = -3, size = 4.5, color = 'grey32', family='sans') +
annotate('text', label = expression(bold('\u2013' * '6 ' * '\u03bc' * 'V')), x = -29, y = 6, size = 4.5, color = 'grey32', family='sans')
print(plot_GroupAndElectrode)
output$downloadPlot.1 &amp;lt;- downloadHandler(
filename &amp;lt;- function(file){
paste0(input$var.Group, ' group, electrode ', input$var.Electrodes.1, ', ', Sys.Date(), '.png')},
content &amp;lt;- function(file){
png(file, units='in', width=13, height=5, res=900)
print(plot_GroupAndElectrode)
dev.off()},
contentType = 'image/png')
} )
&lt;/code>&lt;/pre>
&lt;pre>&lt;code># From ui.R script
downloadButton('downloadPlot.1', 'Download HD plot')
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>&lt;em>Rising to the challenge&lt;/em>&lt;/strong>&lt;/p>
&lt;p>My experience with R Shiny has been so good I've been
&lt;a href="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/">sharing it&lt;/a>. Yet, on my first crawling days, I spent an eternity stuck with this elephant in my room: &amp;quot;μ&amp;quot;. This &lt;em>μ&lt;/em> letter (micro-souvenir from hell, as I later knew it), was part of the labels of my plots. All I knew was that I could not deploy the app online, even while I could perfectly launch it locally in my laptop. So, I wondered what use it was to deploy locally if I couldn't publish the app?! Eventually, I read about UTF-8 encoding in one forum. Bless them forums. All I had to do was use &amp;quot;Âμ&amp;quot; instead of the single &amp;quot;μ&amp;quot;. A better option I found later was: &lt;code>expression(&amp;quot;\u03bc&amp;quot;)&lt;/code>.&lt;/p>
&lt;p>Beyond encoding issues, I had a tough time embedding images. You know, the 'www' folder... To be honest, I still haven't handled the 'www' way--but where there's a will, there's a way. I managed to include my images by uploading them to a website and then entering their URL in &amp;quot;img(src&amp;quot;, avoiding the use of folder paths.&lt;/p>
&lt;pre>&lt;code>img(src=&amp;quot;https://preview.ibb.co/n7qiYR/EEG_montage.png 1&amp;quot;, height=500, width=1000)
&lt;/code>&lt;/pre>
&lt;p>Long after I had built the app, I added another image--the &lt;em>favicon&lt;/em> (the little icon on the browser tab).&lt;/p>
&lt;pre>&lt;code>tags$head(tags$link(rel=&amp;quot;shortcut icon&amp;quot;, href=&amp;quot;https://image.ibb.co/fXUwzb/favic.png&amp;quot;)), # web favicon
&lt;/code>&lt;/pre>
&lt;h3 id="reference">Reference&lt;/h3>
&lt;p>Bernabeu, P., Willems, R. M., &amp;amp; Louwerse, M. M. (2017). Modality switch effects emerge early and increase throughout conceptual processing: Evidence from ERPs [Web application]. Retrieved from &lt;a href="https://pablobernabeu.shinyapps.io/ERP-waveform-visualization_CMS-experiment">https://pablobernabeu.shinyapps.io/ERP-waveform-visualization_CMS-experiment&lt;/a>&lt;/p></description><category>web application</category><category>data dashboard</category><category>R</category><category>R Shiny</category><category>conceptual modality switch</category><category>conceptual processing</category><category>reading</category><category>event-related potentials</category><category>cognition</category><category>psycholinguistics</category><category>HTML</category><category>CSS</category><category>conceptual processing</category><category>R</category><category>web application</category><category>research and teaching applications</category></item><item><title>The case for data dashboards: First steps in R Shiny</title><link>https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/</link><pubDate>Sun, 01 Jan 2017 00:00:00 +0000</pubDate><guid>https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/</guid><description>
&lt;div style="font-size:110%;">
&lt;b> Dashboards for data visualisation, such as &lt;a href="https://shiny.rstudio.com/">R Shiny&lt;/a> and &lt;a href="https://www.tableau.com/">Tableau&lt;/a>, allow the interactive exploration of data by means of drop-down lists and checkboxes, with no coding required from the final users. These web applications can be useful for both the data analyst and the public at large. &lt;/b>
&lt;/div>
&lt;div style="margin-top: 4%;">
&lt;/div>
&lt;p>&lt;img style = "float: right; margin-left: 30px;" width = "25%" src="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/1.jpg" alt="OSF repository file listing for the modality switch experiment, with data files in a Dropbox folder" />&lt;/p>
&lt;p>Visualisation apps run on internet browsers. This allows for three options: private viewing (useful during analysis), selective sharing (used within work groups), or internet publication. Among the available platforms, &lt;a href="https://shiny.rstudio.com/">R Shiny&lt;/a> and &lt;a href="https://www.tableau.com/">Tableau&lt;/a> stand out due to being relatively accessible to new users. Apps serve a broad variety of purposes (see &lt;a href="https://shiny.rstudio.com/gallery/">this gallery&lt;/a> and &lt;a href="https://www.tableau.com/products/desktop">this one&lt;/a>). In science and beyond, these apps allow us to go &lt;a href="https://www.frontiersin.org/articles/10.3389/fpsyg.2015.01782/full">the extra mile in sharing data&lt;/a>. Alongside files and code shared in repositories, we can present the data in a website, in the form of plots or tables. This facilitates the public exploration of each section of the data (groups, participants, trials…) &lt;a href="https://www.nature.com/articles/d41586-019-01506-x">to anyone interested, and allows researchers to account for their proceeding&lt;/a> in the analysis.&lt;/p>
&lt;p>&lt;img width = '70%' src='https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/2.png' alt="Graphic titled Online visualisation apps in science, with The Extra Mile logo over an ERP waveform dashboard" />&lt;/p>
&lt;p>&lt;img style = "float: right; margin-left: 30px;" width = '60%' src='https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/3.png' alt="Elsevier author services Data Visualization page encouraging researchers to share their data" />&lt;/p>
&lt;p>Publishers and journals highly encourage authors to make the most of their data by facilitating its easy exploration by the readership–even though they don’t normally offer the possibility of hosting any web applications yet.&lt;/p>
&lt;p>Apps can also prove valuable to those analysing the data. For instance, my app helped me to identify the extent of noise in a section of the data. Instead of running through a heavy score of code, the drop-down lists of the app let me seamlessly surf through the different sections.&lt;/p>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/4.png" alt="ERP waveform dashboard for Participant 1, anterior brain area, comparing three context-target conditions" />&lt;/p>
&lt;p>At a certain point, I found a data section that was consistently noisier than the rest, and eventually I had to discard it from further statistical analyses. Yet, instead of removing that from the app, I maintained it with a note attached. This particular trait in the data was rather salient.&lt;/p>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/5.png" alt="ERP waveform dashboard for Participant 7, anterior brain area, showing a noticeably noisier signal" />&lt;/p>
&lt;p>Beyond such a salient feature in the data, a visualisation app may also help to spot subtler patterns such as third variables or individual differences.&lt;/p>
&lt;p>There are several platforms for creating apps (e.g., Tableau, D3.js, and R Shiny). I focus on R Shiny here for three reasons: it is affordable to use, fairly accessible to new users, and well suited for science as it is based on the R language (see for instance &lt;a href="https://doi.org/10.1080/10691898.2018.1436999">this article&lt;/a>).&lt;/p>
&lt;div id="how-to-shiny" class="section level4">
&lt;h4>How to Shiny&lt;/h4>
&lt;p>&lt;img style = "float: right; margin-left: 30px;" width = '30%' src='https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/6.png' alt="The five file areas of a Shiny app: Data, server, ui, Shiny deployer, and rsconnect folder" />&lt;/p>
&lt;p>Shiny apps draw on any standard R code that you may already have. This is most commonly plots or tables, but other stuff such as images or Markdown texts are valid too. This is a nice thing to keep in mind when having to create a new app. Part of the job may already be done! The app is distributed among five different areas.&lt;/p>
&lt;ul>
&lt;li>Data file(s): These are any data files you’re using (e.g., with csv or rds extensions).&lt;/li>
&lt;/ul>
&lt;div id="a.-server.r-script" class="section level5">
&lt;h5>1a. &lt;code>server.R&lt;/code> script&lt;/h5>
&lt;p>The &lt;code>server&lt;/code> script contains the central processes: plots, tables, etc. Code that existed independently of the app app may be brought into this script by slightly adapting it. At the top, call the &lt;code>shiny&lt;/code> library and any others used (e.g., ‘ggplot2’), and also read in the data. The snippet below shows the beginning of an example &lt;code>server.R&lt;/code> script.&lt;/p>
&lt;pre>&lt;code>
# server
library(shiny)
library(ggplot2)
EEG.ParticipantAndElectrode = readRDS(&amp;#39;EEG.ParticipantAndElectrode.rds&amp;#39;)
EEG.ParticipantAndBrainArea = readRDS(&amp;#39;EEG.ParticipantAndBrainArea.rds&amp;#39;)
EEG.GroupAndElectrode = readRDS(&amp;#39;EEG.GroupAndElectrode.rds&amp;#39;)
EEG.OLDGroupAndElectrode = readRDS(&amp;#39;EEG.OLDGroupAndElectrode.rds&amp;#39;)
server =
shinyServer(
function(input, output) {
# plot_GroupAndElectrode:
output$plot_GroupAndElectrode &amp;lt;- renderPlot({
dfelectrode &amp;lt;- aggregate(microvolts ~ electrode*time*condition,
EEG.GroupAndElectrode[EEG.GroupAndElectrode$RT.based_Groups==input$var.Group,], mean)
df2 &amp;lt;- subset(dfelectrode, electrode == input$var.Electrodes.1)
df2$condition= as.factor(df2$condition)
df2$condition &amp;lt;- gsub(&amp;#39;visual2visual&amp;#39;, &amp;#39; Visual / Visual&amp;#39;, df2$condition)
df2$condition &amp;lt;- gsub(&amp;#39;haptic2visual&amp;#39;, &amp;#39; Haptic / Visual&amp;#39;, df2$condition)
df2$condition &amp;lt;- gsub(&amp;#39;auditory2visual&amp;#39;, &amp;#39; Auditory / Visual&amp;#39;, df2$condition)
df2$time &amp;lt;- as.integer(as.character(df2$time))
colours &amp;lt;- c(&amp;#39;firebrick1&amp;#39;, &amp;#39;dodgerblue&amp;#39;, &amp;#39;forestgreen&amp;#39;)
# green:visual2visual, blue:haptic2visual, red:auditory2visual
spec_title = paste0(&amp;#39;ERP waveforms for &amp;#39;, input$var.Group, &amp;#39; Group, Electrode &amp;#39;, input$var.Electrodes.1, &amp;#39; (negative values upward; time windows displayed)&amp;#39;)
plot_GroupAndElectrode = ggplot(df2, aes(x=time, y=-microvolts, color=condition)) +
geom_rect(xmin=160, xmax=216, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=270, xmax=370, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=350, xmax=550, ymin=8, ymax=-7.5, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=500, xmax=750, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_line(size=1, alpha = 1) + scale_linetype_manual(values=colours) +
scale_y_continuous(limits=c(-8.38, 8.3), breaks=seq(-8,8,by=1), expand = c(0,0.1)) +
scale_x_continuous(limits=c(-208,808),breaks=seq(-200,800,by=100), expand = c(0.005,0), labels= c(&amp;#39;-200&amp;#39;,&amp;#39;-100 ms&amp;#39;,&amp;#39;0&amp;#39;,&amp;#39;100 ms&amp;#39;,&amp;#39;200&amp;#39;,&amp;#39;300 ms&amp;#39;,&amp;#39;400&amp;#39;,&amp;#39;500 ms&amp;#39;,&amp;#39;600&amp;#39;,&amp;#39;700 ms&amp;#39;,&amp;#39;800&amp;#39;)) +
ggtitle(spec_title) + theme_bw() + geom_vline(xintercept=0) +
annotate(geom=&amp;#39;segment&amp;#39;, y=seq(-8,8,1), yend=seq(-8,8,1), x=-4, xend=8, color=&amp;#39;black&amp;#39;) +
annotate(geom=&amp;#39;segment&amp;#39;, y=-8.2, yend=-8.38, x=seq(-200,800,100), xend=seq(-200,800,100), color=&amp;#39;black&amp;#39;) +
geom_segment(x = -200, y = 0, xend = 800, yend = 0, size=0.5, color=&amp;#39;black&amp;#39;) +
theme(legend.position = c(0.100, 0.150), legend.background = element_rect(fill=&amp;#39;#EEEEEE&amp;#39;, size=0),
axis.title=element_blank(), legend.key.width = unit(1.2,&amp;#39;cm&amp;#39;), legend.text=element_text(size=17),
legend.title = element_text(size=17, face=&amp;#39;bold&amp;#39;), plot.title= element_text(size=20, hjust = 0.5, vjust=2),
axis.text.y = element_blank(), axis.text.x = element_text(size = 14, vjust= 2.12, face=&amp;#39;bold&amp;#39;, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;),
axis.ticks=element_blank(), panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), plot.margin = unit(c(0.1,0.1,0,0), &amp;#39;cm&amp;#39;)) +
annotate(&amp;#39;segment&amp;#39;, x=160, xend=216, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=270, xend=370, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=350, xend=550, y=-7.5, yend=-7.5, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=500, xend=750, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
scale_fill_manual(name = &amp;#39;Context / Target trial&amp;#39;, values=colours) +
scale_color_manual(name = &amp;#39;Context / Target trial&amp;#39;, values=colours) +
guides(linetype=guide_legend(override.aes = list(size=1.2))) +
guides(color=guide_legend(override.aes = list(size=2.5))) +
# Print y axis labels within plot area:
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;\u2013&amp;#39; * &amp;#39;3 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = 3, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;) +
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;+3 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = -3, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;) +
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;\u2013&amp;#39; * &amp;#39;6 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = 6, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;)
print(plot_GroupAndElectrode)
output$downloadPlot.1 &amp;lt;- downloadHandler(
filename &amp;lt;- function(file){
paste0(input$var.Group, &amp;#39; group, electrode &amp;#39;, input$var.Electrodes.1, &amp;#39;, &amp;#39;, Sys.Date(), &amp;#39;.png&amp;#39;)},
content &amp;lt;- function(file){
png(file, units=&amp;#39;in&amp;#39;, width=13, height=5, res=900)
print(plot_GroupAndElectrode)
dev.off()},
contentType = &amp;#39;image/png&amp;#39;)
} )
# ...
&lt;/code>&lt;/pre>
&lt;p>&lt;a href="https://osf.io/uj8z4/">— Whole script&lt;/a>&lt;/p>
&lt;/div>
&lt;div id="b.-ui.r-script" class="section level5">
&lt;h5>1b. &lt;code>ui.R&lt;/code> script&lt;/h5>
&lt;p>The &lt;code>ui&lt;/code> script defines the user interface. For instance, a factor column in the data that has multiple categories may be neatly displayed with a drop-down list on the side bar of the website. The interface may present a central plot before by a legend key below. The snippet below shows the beginning of an example &lt;code>ui.R&lt;/code> script.&lt;/p>
&lt;pre>&lt;code>
# UI
library(shiny)
library(ggplot2)
EEG.GroupAndElectrode = readRDS(&amp;#39;EEG.GroupAndElectrode.rds&amp;#39;)
EEG.ParticipantAndBrainArea = readRDS(&amp;#39;EEG.ParticipantAndBrainArea.rds&amp;#39;)
EEG.ParticipantAndElectrode = readRDS(&amp;#39;EEG.ParticipantAndElectrode.rds&amp;#39;)
EEG.OLDGroupAndElectrode = readRDS(&amp;#39;EEG.OLDGroupAndElectrode.rds&amp;#39;)
ui =
shinyUI(
fluidPage(
tags$head(tags$link(rel=&amp;#39;shortcut icon&amp;#39;, href=&amp;#39;https://image.ibb.co/fXUwzb/favic.png&amp;#39;)), # web favicon
tags$meta(charset=&amp;#39;UTF-8&amp;#39;),
tags$meta(name=&amp;#39;description&amp;#39;, content=&amp;#39;This R Shiny visualisation dashboard presents data from a psycholinguistic ERP experiment (Bernabeu et al., 2017).&amp;#39;),
tags$meta(name=&amp;#39;keywords&amp;#39;, content=&amp;#39;R, Shiny, ggplot2, visualisation, data, psycholinguistics, conceptual processing, modality switch, embodied cognition&amp;#39;),
tags$meta(name=&amp;#39;viewport&amp;#39;, content=&amp;#39;width=device-width, initial-scale=1.0&amp;#39;),
titlePanel(h3(strong(&amp;#39;Waveforms in detail from an ERP experiment on the Conceptual Modality Switch&amp;#39;), a(&amp;#39;(Bernabeu et al., 2017)&amp;#39;,
href=&amp;#39;https://figshare.com/articles/EEG_study_on_conceptual_modality-switching_Bernabeu_et_al_in_prep_/4210863&amp;#39;, target=&amp;#39;_blank&amp;#39;,
style = &amp;#39;color:#3E454E; text-decoration:underline; font-weight:normal&amp;#39;), align = &amp;#39;center&amp;#39;, style = &amp;#39;color:black&amp;#39;),
windowTitle = &amp;#39;Visualization of ERP waveforms from experiment on Conceptual Modality Switch (Bernabeu et al., 2017)&amp;#39;),
sidebarLayout(
sidebarPanel(width = 2,
# Condition 1 for reactivity between tabs and sidebars
conditionalPanel(
condition = &amp;#39;input.tabvals == 1&amp;#39;,
h5(a(strong(&amp;#39;See paper, statistics, all data.&amp;#39;), &amp;#39;Plots by group and brain area shown in paper.&amp;#39;,
href=&amp;#39;https://figshare.com/articles/EEG_study_on_conceptual_modality-switching_Bernabeu_et_al_in_prep_/4210863&amp;#39;,
target=&amp;#39;_blank&amp;#39;), align = &amp;#39;center&amp;#39;),
br(),
selectInput(&amp;#39;var.Group&amp;#39;, label = &amp;#39;Group&amp;#39;, choices = list(&amp;#39;Quick&amp;#39;,&amp;#39;Slow&amp;#39;), selected = &amp;#39;Quick&amp;#39;),
h6(&amp;#39;Quick G.: 23 participants&amp;#39;),
h6(&amp;#39;Slow G.: 23 participants&amp;#39;),
br(),
selectInput(&amp;#39;var.Electrodes.1&amp;#39;, label = h5(strong(&amp;#39;Electrode&amp;#39;), br(), &amp;#39;(see montage below)&amp;#39;),
choices = list(&amp;#39;1&amp;#39;,&amp;#39;2&amp;#39;,&amp;#39;3&amp;#39;,&amp;#39;4&amp;#39;,&amp;#39;5&amp;#39;,&amp;#39;6&amp;#39;,&amp;#39;7&amp;#39;,&amp;#39;8&amp;#39;,&amp;#39;9&amp;#39;,&amp;#39;10&amp;#39;,
&amp;#39;11&amp;#39;,&amp;#39;12&amp;#39;,&amp;#39;13&amp;#39;,&amp;#39;14&amp;#39;,&amp;#39;15&amp;#39;,&amp;#39;16&amp;#39;,&amp;#39;17&amp;#39;,&amp;#39;18&amp;#39;,&amp;#39;19&amp;#39;,&amp;#39;20&amp;#39;,&amp;#39;21&amp;#39;,
&amp;#39;22&amp;#39;,&amp;#39;23&amp;#39;,&amp;#39;24&amp;#39;,&amp;#39;25&amp;#39;,&amp;#39;26&amp;#39;,&amp;#39;27&amp;#39;,&amp;#39;28&amp;#39;,&amp;#39;29&amp;#39;,&amp;#39;30&amp;#39;,&amp;#39;31&amp;#39;,&amp;#39;33&amp;#39;,
&amp;#39;34&amp;#39;,&amp;#39;35&amp;#39;,&amp;#39;36&amp;#39;,&amp;#39;37&amp;#39;,&amp;#39;38&amp;#39;,&amp;#39;39&amp;#39;,&amp;#39;40&amp;#39;,&amp;#39;41&amp;#39;,&amp;#39;42&amp;#39;,&amp;#39;43&amp;#39;,&amp;#39;44&amp;#39;,
&amp;#39;45&amp;#39;,&amp;#39;46&amp;#39;,&amp;#39;47&amp;#39;,&amp;#39;48&amp;#39;,&amp;#39;49&amp;#39;,&amp;#39;50&amp;#39;,&amp;#39;51&amp;#39;,&amp;#39;52&amp;#39;,&amp;#39;53&amp;#39;,&amp;#39;54&amp;#39;,&amp;#39;55&amp;#39;,
&amp;#39;56&amp;#39;,&amp;#39;57&amp;#39;,&amp;#39;58&amp;#39;,&amp;#39;59&amp;#39;,&amp;#39;60&amp;#39;), selected = &amp;#39;30&amp;#39; ),
br(), br(),
h6(&amp;#39;Source code:&amp;#39;),
h6(strong(&amp;#39;- &amp;#39;), a(&amp;#39;server.R&amp;#39;, href=&amp;#39;https://osf.io/uj8z4/&amp;#39;, target=&amp;#39;_blank&amp;#39;, style = &amp;#39;text-decoration: underline;&amp;#39;)),
h6(strong(&amp;#39;- &amp;#39;), a(&amp;#39;ui.R&amp;#39;, href=&amp;#39;https://osf.io/8bwcx/&amp;#39;, target=&amp;#39;_blank&amp;#39;, style = &amp;#39;text-decoration: underline;&amp;#39;)),
br(),
h6(a(&amp;#39;CC-By 4.0 License&amp;#39;, href=&amp;#39;https://osf.io/97unm/&amp;#39;, target=&amp;#39;_blank&amp;#39;), align = &amp;#39;center&amp;#39;, style = &amp;#39;text-decoration: underline;&amp;#39;),
br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(),
br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(), br(),
h5(a(strong(&amp;#39;See paper, statistics, all data.&amp;#39;),
href=&amp;#39;https://figshare.com/articles/EEG_study_on_conceptual_modality-switching_Bernabeu_et_al_in_prep_/4210863&amp;#39;,
target=&amp;#39;_blank&amp;#39;), align = &amp;#39;center&amp;#39;),
br(), br(), br(), br(), br(), br(), br(), br()
),
# ...
&lt;/code>&lt;/pre>
&lt;p>&lt;a href="https://osf.io/8bwcx">— Whole script&lt;/a>&lt;/p>
&lt;/div>
&lt;div id="deployment-and-logs" class="section level5">
&lt;h5>2. Deployment and logs&lt;/h5>
&lt;p>This script contains the commands for deploying the app on- or off-line, and for checking the session logs in case of any errors.&lt;/p>
&lt;/div>
&lt;div id="automatically-created-folder" class="section level5">
&lt;h5>3. Automatically created folder&lt;/h5>
&lt;p>When the app is first deployed on the internet, a subfolder is automatically created with the name ‘rsconnect’. This folder contains a text file which can be used to modify the URL and the title of the webpage.&lt;/p>
&lt;p>Steps to create a Shiny app from scratch:&lt;/p>
&lt;p>&lt;a href="https://shiny.rstudio.com/articles/shinyapps.html">&lt;strong>1. Tutorials (link).&lt;/strong> Being open-source software, excellent directions are available through a Google search.&lt;/a>&lt;/p>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/7.png" alt="Google search results for r shiny tutorial, listing video tutorials, blogs and galleries with code" />&lt;/p>
&lt;p>&lt;a href="https://shiny.rstudio.com/articles/shinyapps.html">The core ideas are:&lt;/a>&lt;/p>
&lt;p>As mentioned above, create a &lt;code>ui.R&lt;/code> script for the code containing the user interface, and create a &lt;code>server.R&lt;/code> script for the code containing the main content (your plots / tables, etc).&lt;/p>
&lt;p>At the top of both ui.R and server.R scripts, enter the command &lt;code>library(shiny)&lt;/code> and also load any other libraries you’re using (e.g., &lt;code>ggplot2&lt;/code>).&lt;/p>
&lt;p>Test your app by deploying it locally, before launching online. For this purpose, first save the &lt;code>ui&lt;/code> and &lt;code>server&lt;/code> parts independently, as in:&lt;/p>
&lt;pre>&lt;code>
ui =
shinyUI(
fluidPage(
# ...
&lt;/code>&lt;/pre>
&lt;p>Then deploy locally by running:&lt;/p>
&lt;pre>&lt;code>shinyApp(ui, server)&lt;/code>&lt;/pre>
&lt;p>Managing to run the app locally is a great first step before launching online (which may sometimes prove a bit trickier).&lt;/p>
&lt;p>&lt;a href="https://shiny.rstudio.com/articles/shinyapps.html">&lt;strong>2. User token (link).&lt;/strong> Sign up and read in your private key—just to be done once in a computer.&lt;/a>&lt;/p>
&lt;p>&lt;strong>3. Go for it.&lt;/strong> After locally testing and saving the two main scripts (&lt;code>ui.R&lt;/code> and &lt;code>server.R&lt;/code>), run &lt;code>deployApp()&lt;/code> to launch the app online.&lt;/p>
&lt;p>&lt;strong>4. Bugs and session logs.&lt;/strong> Most often they won’t be bugs actually, but fancies, as it were. For instance, some special characters have to get even more special (technically, UTF-8 encoding). For a character such as ‘μ’, Shiny prefers ‘Âμ’, or better, the Unicode &lt;code>expression("\u03bc")&lt;/code>.&lt;/p>
&lt;p>Cling to your logs by calling the line below, which you may keep at hand in your ‘Shiny deployer.R’ script.&lt;/p>
&lt;pre>&lt;code>showLogs(appPath = getwd(), appFile = NULL, appName = NULL, account = NULL,
entries = 50, streaming = FALSE)&lt;/code>&lt;/pre>
&lt;p>At best, the log output will mention any typos and unaccepted characters, pointing to specific lines in your code.&lt;/p>
&lt;p>It may take a couple of intense days to get a first Shiny app running. Although the usual rabbit holes do exist, years of Shiny have already yielded a sizeable body of free resources online (tutorials, blogs, vlogs). Moreover, there’s also &lt;a href="https://community.rstudio.com/">the RStudio Community&lt;/a>, and then StackOverflow etc., where you can post any needs/despair. Post your code, log, and explanation, and you’ll be rescued out in a couple of days. Long live those contributors.&lt;/p>
&lt;p>It’s sometimes enough to upload a bare app, but you might then think it can look better.&lt;/p>
&lt;p>&lt;strong>5&lt;/strong> (optional). &lt;strong>Advance.&lt;/strong> Use tabs to combine multiple apps on one webpage, use different widgets, include a download option, etc. Tutorials like &lt;a href="https://www.youtube.com/watch?v=Q9sRKkaNveI">this one on Youtube&lt;/a> can take you there, especially those that provide the code, as in the description of that video. Use those scripts as templates. For example, I made use of tabs on the top of the dashboard in order to keep the side bar from having too many widgets. The appearance of these tabs can be adjusted. More importantly, the inputs in the sidebar can be modified depending on the active tab, by means of ‘reactivity’ conditions.&lt;/p>
&lt;pre>&lt;code>
mainPanel(
tags$style(HTML(&amp;#39;
.tabbable &amp;gt; .nav &amp;gt; li &amp;gt; a {background-color:white; color:#3E454E}
.tabbable &amp;gt; .nav &amp;gt; li &amp;gt; a:hover {background-color:#002555; color:white}
.tabbable &amp;gt; .nav &amp;gt; li[class=active] &amp;gt; a {background-color:#ECF4FF; color:black}
.tabbable &amp;gt; .nav &amp;gt; li[class=active] &amp;gt; a:hover {background-color:#E7F1FF; color:black}
&amp;#39;)),
tabsetPanel(id=&amp;#39;tabvals&amp;#39;,
tabPanel(value=1, h4(strong(&amp;#39;Group &amp;amp; Electrode&amp;#39;)), br(), plotOutput(&amp;#39;plot_GroupAndElectrode&amp;#39;),
h5(a(strong(&amp;#39;See plots with 95% Confidence Intervals&amp;#39;), href=&amp;#39;https://osf.io/2tpxn/&amp;#39;,
target=&amp;#39;_blank&amp;#39;), style=&amp;#39;text-decoration: underline;&amp;#39;),
downloadButton(&amp;#39;downloadPlot.1&amp;#39;, &amp;#39;Download HD plot&amp;#39;), br(), br(),
# EEG montage
img(src=&amp;#39;https://preview.ibb.co/n7qiYR/EEG_montage.png&amp;#39;, height=500, width=1000)),
tabPanel(value=2, h4(strong(&amp;#39;Participant &amp;amp; Area&amp;#39;)), br(), plotOutput(&amp;#39;plot_ParticipantAndLocation&amp;#39;),
h5(a(strong(&amp;#39;See plots with 95% Confidence Intervals&amp;#39;), href=&amp;#39;https://osf.io/86ch9/&amp;#39;,
target=&amp;#39;_blank&amp;#39;), style=&amp;#39;text-decoration: underline;&amp;#39;),
downloadButton(&amp;#39;downloadPlot.2&amp;#39;, &amp;#39;Download HD plot&amp;#39;), br(), br(),
# EEG montage
img(src=&amp;#39;https://preview.ibb.co/n7qiYR/EEG_montage.png&amp;#39;, height=500, width=1000)),
tabPanel(value=3, h4(strong(&amp;#39;Participant &amp;amp; Electrode&amp;#39;)), br(), plotOutput(&amp;#39;plot_ParticipantAndElectrode&amp;#39;),
br(), downloadButton(&amp;#39;downloadPlot.3&amp;#39;, &amp;#39;Download HD plot&amp;#39;), br(), br(),
# EEG montage
img(src=&amp;#39;https://preview.ibb.co/n7qiYR/EEG_montage.png&amp;#39;, height=500, width=1000)),
tabPanel(value=4, h4(strong(&amp;#39;OLD Group &amp;amp; Electrode&amp;#39;)), br(), plotOutput(&amp;#39;plot_OLDGroupAndElectrode&amp;#39;),
h5(a(strong(&amp;#39;See plots with 95% Confidence Intervals&amp;#39;), href=&amp;#39;https://osf.io/dvs2z/&amp;#39;,
target=&amp;#39;_blank&amp;#39;), style=&amp;#39;text-decoration: underline;&amp;#39;),
downloadButton(&amp;#39;downloadPlot.4&amp;#39;, &amp;#39;Download HD plot&amp;#39;), br(), br(),
# EEG montage
img(src=&amp;#39;https://preview.ibb.co/n7qiYR/EEG_montage.png&amp;#39;, height=500, width=1000))
),
&lt;/code>&lt;/pre>
&lt;p>The &lt;a href="https://shiny.rstudio.com/gallery/">official Shiny gallery&lt;/a> offers a great array of apps including their code (e.g., &lt;a href="https://shiny.rstudio.com/gallery/kmeans-example.html">basic example&lt;/a>). Another feature you may add is the option to download your plots, tables, data…&lt;/p>
&lt;pre>&lt;code>
# In ui.R script
downloadButton(&amp;#39;downloadPlot.1&amp;#39;, &amp;#39;Download HD plot&amp;#39;)
#___________________________________________________
# In server.R script
spec_title = paste0(&amp;#39;ERP waveforms for &amp;#39;, input$var.Group, &amp;#39; Group, Electrode &amp;#39;, input$var.Electrodes.1, &amp;#39; (negative values upward; time windows displayed)&amp;#39;)
plot_GroupAndElectrode = ggplot(df2, aes(x=time, y=-microvolts, color=condition)) +
geom_rect(xmin=160, xmax=216, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=270, xmax=370, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=350, xmax=550, ymin=8, ymax=-7.5, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_rect(xmin=500, xmax=750, ymin=7.5, ymax=-8, color = &amp;#39;grey75&amp;#39;, fill=&amp;#39;black&amp;#39;, alpha=0, linetype=&amp;#39;longdash&amp;#39;) +
geom_line(size=1, alpha = 1) + scale_linetype_manual(values=colours) +
scale_y_continuous(limits=c(-8.38, 8.3), breaks=seq(-8,8,by=1), expand = c(0,0.1)) +
scale_x_continuous(limits=c(-208,808),breaks=seq(-200,800,by=100), expand = c(0.005,0), labels= c(&amp;#39;-200&amp;#39;,&amp;#39;-100 ms&amp;#39;,&amp;#39;0&amp;#39;,&amp;#39;100 ms&amp;#39;,&amp;#39;200&amp;#39;,&amp;#39;300 ms&amp;#39;,&amp;#39;400&amp;#39;,&amp;#39;500 ms&amp;#39;,&amp;#39;600&amp;#39;,&amp;#39;700 ms&amp;#39;,&amp;#39;800&amp;#39;)) +
ggtitle(spec_title) + theme_bw() + geom_vline(xintercept=0) +
annotate(geom=&amp;#39;segment&amp;#39;, y=seq(-8,8,1), yend=seq(-8,8,1), x=-4, xend=8, color=&amp;#39;black&amp;#39;) +
annotate(geom=&amp;#39;segment&amp;#39;, y=-8.2, yend=-8.38, x=seq(-200,800,100), xend=seq(-200,800,100), color=&amp;#39;black&amp;#39;) +
geom_segment(x = -200, y = 0, xend = 800, yend = 0, size=0.5, color=&amp;#39;black&amp;#39;) +
theme(legend.position = c(0.100, 0.150), legend.background = element_rect(fill=&amp;#39;#EEEEEE&amp;#39;, size=0),
axis.title=element_blank(), legend.key.width = unit(1.2,&amp;#39;cm&amp;#39;), legend.text=element_text(size=17),
legend.title = element_text(size=17, face=&amp;#39;bold&amp;#39;), plot.title= element_text(size=20, hjust = 0.5, vjust=2),
axis.text.y = element_blank(), axis.text.x = element_text(size = 14, vjust= 2.12, face=&amp;#39;bold&amp;#39;, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;),
axis.ticks=element_blank(), panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), plot.margin = unit(c(0.1,0.1,0,0), &amp;#39;cm&amp;#39;)) +
annotate(&amp;#39;segment&amp;#39;, x=160, xend=216, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=270, xend=370, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=350, xend=550, y=-7.5, yend=-7.5, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
annotate(&amp;#39;segment&amp;#39;, x=500, xend=750, y=-8, yend=-8, colour = &amp;#39;grey75&amp;#39;, size = 1.5) +
scale_fill_manual(name = &amp;#39;Context / Target trial&amp;#39;, values=colours) +
scale_color_manual(name = &amp;#39;Context / Target trial&amp;#39;, values=colours) +
guides(linetype=guide_legend(override.aes = list(size=1.2))) +
guides(color=guide_legend(override.aes = list(size=2.5))) +
# Print y axis labels within plot area:
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;\u2013&amp;#39; * &amp;#39;3 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = 3, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;) +
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;+3 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = -3, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;) +
annotate(&amp;#39;text&amp;#39;, label = expression(bold(&amp;#39;\u2013&amp;#39; * &amp;#39;6 &amp;#39; * &amp;#39;\u03bc&amp;#39; * &amp;#39;V&amp;#39;)), x = -29, y = 6, size = 4.5, color = &amp;#39;grey32&amp;#39;, family=&amp;#39;sans&amp;#39;)
print(plot_GroupAndElectrode)
output$downloadPlot.1 &amp;lt;- downloadHandler(
filename &amp;lt;- function(file){
paste0(input$var.Group, &amp;#39; group, electrode &amp;#39;, input$var.Electrodes.1, &amp;#39;, &amp;#39;, Sys.Date(), &amp;#39;.png&amp;#39;)},
content &amp;lt;- function(file){
png(file, units=&amp;#39;in&amp;#39;, width=13, height=5, res=900)
print(plot_GroupAndElectrode)
dev.off()},
contentType = &amp;#39;image/png&amp;#39;)
} )
&lt;/code>&lt;/pre>
&lt;p>Apps can include any text, such as explanations of any length and web links. For instance, we can link back to the data repository, where the code for the app can be found.&lt;/p>
&lt;p>&lt;img src="https://pablobernabeu.github.io/2017/the-case-for-data-dashboards-first-steps-in-r-shiny/8.png" alt="OSF server.R script view, with a green arrow looping back to the project's data repository" />&lt;/p>
&lt;p>An example of a &lt;a href="https://pablobernabeu.shinyapps.io/ERP-waveform-visualization_CMS-experiment/">Shiny app is available&lt;/a>, which may also be &lt;a href="https://mybinder.org/v2/gh/pablobernabeu/Modality-switch-effects-emerge-early-and-increase-throughout-conceptual-processing/master?urlpath=rstudio">edited and run in this RStudio environment&lt;/a>, inside the ‘Shiny-app’ folder.&lt;/p>
&lt;p>The Shiny server (shinyapps.io) allows publishing dashboards built with various frameworks besides Shiny proper. &lt;a href="https://rmarkdown.rstudio.com/flexdashboard/">Flexdashboard&lt;/a> and &lt;a href="https://rstudio.github.io/shinydashboard/">Shinydashboard&lt;/a> are two of these frameworks, which have visible advantages over basic Shiny, in terms of layout. An &lt;a href="https://pablobernabeu.shinyapps.io/Dutch-modality-exclusivity-norms/">example with Flexdashboard is available&lt;/a>.&lt;/p>
&lt;p align="center">
★ &lt;b> Flexdashboard &lt;/b> ★
&lt;/p>
&lt;p align="center">
★ ★ &lt;b> Shiny &lt;/b> ★ ★
&lt;/p>
&lt;p align="center">
★ ★ ★ &lt;b> Flexdashboard-Shiny &lt;/b> ★ ★ ★
&lt;/p>
&lt;p>&lt;img src="https://raw.githubusercontent.com/pablobernabeu/data-is-present/master/dashboard%20gif.gif" alt="Animated demo of an interactive R Shiny Flexdashboard responding to user selections" />&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="logistics" class="section level4">
&lt;h4>Logistics&lt;/h4>
&lt;p>Memory capacity can become an issue as you go on, which will be flagged in the error logs as: ‘Shiny cannot use on-disk bookmarking’. This doesn’t necessarily lead you to a paid subscription or to &lt;a href="https://www.r-bloggers.com/alternative-approaches-to-scaling-shiny-with-rstudio-shiny-server-shinyproxy-or-custom-architecture/">host the website on a custom server&lt;/a>. Try pruning the data file, outsourcing data sections across the five available apps.&lt;/p>
&lt;p>App providers have specific terms of use. To begin, Shiny has a free starter license with limited use, where free apps can handle a certain amount of data, and up to five apps may be created. Beyond that, RStudio offers a wide range of &lt;a href="http://www.shinyapps.io/#_pricing">subscriptions&lt;/a> starting at $9/month. For its part, Tableau in principle deals only with &lt;a href="https://www.tableau.com/pricing">subscriptions&lt;/a> from $35/month on. While they offer 1-year licenses to students and instructors for free, these don’t include web hosting, unlike Shiny’s free plan. &lt;a href="https://www.linkedin.com/pulse/r-shiny-v-tableau-dawn-graphics-anand-gupta?lipi=urn%3Ali%3Apage%3Ad_flagship3_pulse_read%3BCDbB2MVuQA6l%2BRNxwqWzQg%3D%3D">Further comparisons&lt;/a> of these platforms are available online. Last, I’ll just mention a third language, &lt;a href="https://d3js.org/">D3&lt;/a>, which is powerful, and may also be used &lt;a href="https://rstudio.github.io/r2d3/">through R&lt;/a>.&lt;/p>
&lt;p>In the case of very heavy data or frequent public use, if you don’t want to host your Shiny app externally, you might consider rendering a PDF with your visualisations instead.&lt;/p>
&lt;pre>&lt;code>
pdf(&amp;quot;List of plots per page&amp;quot;, width=13, height=5)
print(plot1)
print(plot2)
# ...
print(plot150)
dev.off()
&lt;/code>&lt;/pre>
&lt;p>High-resolution plots can be rendered into a PDF document in a snap. Conveniently, all text is indexed, so it can be searched (Ctrl+f / Cmd+f / 🔍) (&lt;a href="https://osf.io/2tpxn/">see example&lt;/a>). Furthermore, you may also &lt;a href="http://www.ilovepdf.com/">merge the rendered PDF&lt;/a> with any other documents.&lt;/p>
&lt;div class="document-viewer-container" style="height: 80vh; min-height: 400px;">
&lt;iframe src="https://cdn.jsdelivr.net/gh/pablobernabeu/Modality-switch-effects-emerge-early-and-increase-throughout-conceptual-processing@master/ERPs/Plots/List%20plots%20per%20participant%20and%20brain%20area.pdf" width="100%" height="100%" style="border: none" title="Document Viewer" loading="lazy">
&lt;p>
Your browser does not support embedded PDFs. &lt;a href="https://cdn.jsdelivr.net/gh/pablobernabeu/Modality-switch-effects-emerge-early-and-increase-throughout-conceptual-processing@master/ERPs/Plots/List%20plots%20per%20participant%20and%20brain%20area.pdf" target="_blank">Download the PDF&lt;/a> instead.
&lt;/p>
&lt;/iframe>
&lt;/div>
&lt;/div>
&lt;div id="summary-in-slides" class="section level3">
&lt;h3>Summary in &lt;a href="https://www.slideshare.net/PabloBernabeu/presenting-data-interactively-online-using-r-shiny-126064157">slides&lt;/a>&lt;/h3>
&lt;iframe src="//www.slideshare.net/slideshow/embed_code/key/mDJ6IF1RGTiAR8" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen>
&lt;/iframe>
&lt;div style="margin-bottom:5px">
&lt;strong> &lt;a href="//www.slideshare.net/PabloBernabeu/presenting-data-interactively-online-using-r-shiny-126064157" title="Presenting data interactively online using R Shiny" target="_blank">Presenting data interactively online using R Shiny&lt;/a> &lt;/strong>
&lt;/div>
&lt;/div></description><category>s</category><category>data presentation</category><category>dashboard</category><category>reproducibility</category><category>open science</category><category>open data</category><category>R</category><category>R Shiny</category><category>Flexdashboard</category><category>R</category><category>data dashboards</category><category>open data</category></item></channel></rss>