<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Replicate Weights | FLH Website</title><link>https://francish.net/tags/replicate-weights/</link><atom:link href="https://francish.net/tags/replicate-weights/index.xml" rel="self" type="application/rss+xml"/><description>Replicate Weights</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>en-us</language><lastBuildDate>Thu, 10 Sep 2026 00:00:00 +0000</lastBuildDate><image><url>https://francish.net/media/icon_hu8315282870087596650.png</url><title>Replicate Weights</title><link>https://francish.net/tags/replicate-weights/</link></image><item><title>Example Using Replicate Weights with PISA</title><link>https://francish.net/post/2026_example_rw/</link><pubDate>Thu, 10 Sep 2026 00:00:00 +0000</pubDate><guid>https://francish.net/post/2026_example_rw/</guid><description>&lt;p>As the PISA 2025 results were just released this
&lt;a href="https://www.youtube.com/watch?v=YCDXPD3wRr0" target="_blank" rel="noopener">week&lt;/a> and I am currently
teaching a seminar/class on analyzing international large scale
assessments this fall 2026, I thought it would good to show how we
actually use these replicate weights when analyzing these datasets.
Replicate weights are used to get the correct standard errors when
analyzing ILSAs. I don’t think many applied researchers understand what
these are– even though a lot has been written about them– and are
explained in the documentation of the different ILSAs. It gets confusing
also because different ILSAs (e.g., TIMSS vs. PISA) use different
versions of these (e.g., JK2 vs Fay’s BRR).&lt;/p>
&lt;p>Aside from ILSAs, many other surveys use replicate weights (e.g.,
ECLS-K). I’ll first show how we can use these replicate weights using
base R, then using the &lt;mark>survey&lt;/mark> package, then comparing results from an
web app.&lt;/p>
&lt;p>We’ll use the PISA 2022 dataset for Albania as an example:&lt;/p>
&lt;pre>&lt;code>pisa &amp;lt;- rio::import(&amp;quot;https://raw.githubusercontent.com/flh3/pubdata/refs/heads/main/ILSA/alb_pisa.csv&amp;quot;)
dim(pisa)
[1] 6129 95
names(pisa)
[1] &amp;quot;CNT&amp;quot; &amp;quot;CNTRYID&amp;quot; &amp;quot;W_FSTUWT&amp;quot; &amp;quot;PV1MATH&amp;quot; &amp;quot;PV2MATH&amp;quot; &amp;quot;PV3MATH&amp;quot;
[7] &amp;quot;PV4MATH&amp;quot; &amp;quot;PV5MATH&amp;quot; &amp;quot;PV6MATH&amp;quot; &amp;quot;PV7MATH&amp;quot; &amp;quot;PV8MATH&amp;quot; &amp;quot;PV9MATH&amp;quot;
[13] &amp;quot;PV10MATH&amp;quot; &amp;quot;W_FSTURWT1&amp;quot; &amp;quot;W_FSTURWT2&amp;quot; &amp;quot;W_FSTURWT3&amp;quot; &amp;quot;W_FSTURWT4&amp;quot; &amp;quot;W_FSTURWT5&amp;quot;
[19] &amp;quot;W_FSTURWT6&amp;quot; &amp;quot;W_FSTURWT7&amp;quot; &amp;quot;W_FSTURWT8&amp;quot; &amp;quot;W_FSTURWT9&amp;quot; &amp;quot;W_FSTURWT10&amp;quot; &amp;quot;W_FSTURWT11&amp;quot;
[25] &amp;quot;W_FSTURWT12&amp;quot; &amp;quot;W_FSTURWT13&amp;quot; &amp;quot;W_FSTURWT14&amp;quot; &amp;quot;W_FSTURWT15&amp;quot; &amp;quot;W_FSTURWT16&amp;quot; &amp;quot;W_FSTURWT17&amp;quot;
[31] &amp;quot;W_FSTURWT18&amp;quot; &amp;quot;W_FSTURWT19&amp;quot; &amp;quot;W_FSTURWT20&amp;quot; &amp;quot;W_FSTURWT21&amp;quot; &amp;quot;W_FSTURWT22&amp;quot; &amp;quot;W_FSTURWT23&amp;quot;
[37] &amp;quot;W_FSTURWT24&amp;quot; &amp;quot;W_FSTURWT25&amp;quot; &amp;quot;W_FSTURWT26&amp;quot; &amp;quot;W_FSTURWT27&amp;quot; &amp;quot;W_FSTURWT28&amp;quot; &amp;quot;W_FSTURWT29&amp;quot;
[43] &amp;quot;W_FSTURWT30&amp;quot; &amp;quot;W_FSTURWT31&amp;quot; &amp;quot;W_FSTURWT32&amp;quot; &amp;quot;W_FSTURWT33&amp;quot; &amp;quot;W_FSTURWT34&amp;quot; &amp;quot;W_FSTURWT35&amp;quot;
[49] &amp;quot;W_FSTURWT36&amp;quot; &amp;quot;W_FSTURWT37&amp;quot; &amp;quot;W_FSTURWT38&amp;quot; &amp;quot;W_FSTURWT39&amp;quot; &amp;quot;W_FSTURWT40&amp;quot; &amp;quot;W_FSTURWT41&amp;quot;
[55] &amp;quot;W_FSTURWT42&amp;quot; &amp;quot;W_FSTURWT43&amp;quot; &amp;quot;W_FSTURWT44&amp;quot; &amp;quot;W_FSTURWT45&amp;quot; &amp;quot;W_FSTURWT46&amp;quot; &amp;quot;W_FSTURWT47&amp;quot;
[61] &amp;quot;W_FSTURWT48&amp;quot; &amp;quot;W_FSTURWT49&amp;quot; &amp;quot;W_FSTURWT50&amp;quot; &amp;quot;W_FSTURWT51&amp;quot; &amp;quot;W_FSTURWT52&amp;quot; &amp;quot;W_FSTURWT53&amp;quot;
[67] &amp;quot;W_FSTURWT54&amp;quot; &amp;quot;W_FSTURWT55&amp;quot; &amp;quot;W_FSTURWT56&amp;quot; &amp;quot;W_FSTURWT57&amp;quot; &amp;quot;W_FSTURWT58&amp;quot; &amp;quot;W_FSTURWT59&amp;quot;
[73] &amp;quot;W_FSTURWT60&amp;quot; &amp;quot;W_FSTURWT61&amp;quot; &amp;quot;W_FSTURWT62&amp;quot; &amp;quot;W_FSTURWT63&amp;quot; &amp;quot;W_FSTURWT64&amp;quot; &amp;quot;W_FSTURWT65&amp;quot;
[79] &amp;quot;W_FSTURWT66&amp;quot; &amp;quot;W_FSTURWT67&amp;quot; &amp;quot;W_FSTURWT68&amp;quot; &amp;quot;W_FSTURWT69&amp;quot; &amp;quot;W_FSTURWT70&amp;quot; &amp;quot;W_FSTURWT71&amp;quot;
[85] &amp;quot;W_FSTURWT72&amp;quot; &amp;quot;W_FSTURWT73&amp;quot; &amp;quot;W_FSTURWT74&amp;quot; &amp;quot;W_FSTURWT75&amp;quot; &amp;quot;W_FSTURWT76&amp;quot; &amp;quot;W_FSTURWT77&amp;quot;
[91] &amp;quot;W_FSTURWT78&amp;quot; &amp;quot;W_FSTURWT79&amp;quot; &amp;quot;W_FSTURWT80&amp;quot; &amp;quot;male&amp;quot; &amp;quot;ESCS&amp;quot;
&lt;/code>&lt;/pre>
&lt;p>There are a lot of weights! The overall weight is &lt;mark>W_FSTUWT&lt;/mark> and the 80
replicate weights are those that begin with &lt;mark>W_FSTURWT&lt;/mark>. I explain
elsewhere how these weights are constructed. Know that PISA uses Fay’s
balanced repeated replication (BRR; with rho = .50). BRR is a type of
resampling technique (along with jackknifing and bootstrapping). These
replicate weights use the original sampling weights but are perturbed
with some observations having weights increased by a factor of 1.5 and
others decreased by a factor of .5. These perturbations will result in
different results when we fit the model of interest.&lt;/p>
&lt;p>In essence, to use the weights:&lt;/p>
&lt;ol>
&lt;li>We fit the main model of interest using the &lt;strong>overall&lt;/strong> student
weight (&lt;mark>W_FSTUWT&lt;/mark>) and we get the regression coefficients for this
(we don’t need the standard errors here).&lt;/li>
&lt;li>We then fit 80 models (&lt;em>R&lt;/em> = 80) using &lt;mark>W_FSTURWT1&lt;/mark> to &lt;mark>W_FSTURWT80&lt;/mark>
(instead of &lt;mark>W_FSTUWT&lt;/mark>). These replicate weights will result in 80
sets of different regression coefficients per model fit (i.e.,
&lt;em>θ&lt;/em>&lt;sub>1&lt;/sub> to &lt;em>θ&lt;/em>&lt;sub>80&lt;/sub>. We save all these coefficients
too.&lt;/li>
&lt;li>We use the 80 regression coefficients to compute the standard
errors.&lt;/li>
&lt;/ol>
&lt;p>The standard errors are computed using:&lt;/p>
&lt;p>$\frac{1}{R(1-k)^2}\Sigma(\theta\_{1...R} - \bar{\theta})^2$&lt;/p>
&lt;p>For the case of PISA, &lt;em>k&lt;/em> = .50 (or the Fay factor).The first part of
the formula is an adjustment factor and reduces to&lt;/p>
&lt;p>$\frac{1}{R(1-k)^2}=\frac{1}{80(1-.50)^2}=\frac{1}{20}$&lt;/p>
&lt;h2 id="example-1-manual-method">Example 1: Manual method&lt;/h2>
&lt;p>Let’s say we are interested in seeing how SES and sex predict math
outcomes (we’ll just use one plausible value as an example; I explain
PVs elsewhere). We fit the model of interest:&lt;/p>
&lt;p>&lt;strong>NOTE:&lt;/strong> The &lt;code>lm&lt;/code> function in R uses analytic or precision weights– not
sampling weights!! The point estimates will be ok but the standard
errors are incorrect! However– for this example- we don’t need the
standard errors produced anyway! So, for step 1:&lt;/p>
&lt;pre>&lt;code>orig &amp;lt;- lm(PV1MATH ~ ESCS + male, data = pisa, weight = W_FSTUWT)
cfs &amp;lt;- coef(orig) #save the coefficients
cfs #the coefficients
(Intercept) ESCS male
392.65420 17.68895 -19.97603
&lt;/code>&lt;/pre>
&lt;p>Now for step 2, we fit 80 models. We can just use a loop (easier to
understand for most people):&lt;/p>
&lt;pre>&lt;code>cfs_i &amp;lt;- matrix(NA, 80, 3) #80 models of 3 coefficients
R &amp;lt;- 80 #number of replicate weights
for (i in 1:R){
tmp &amp;lt;- lm(PV1MATH ~ ESCS + male, data = pisa, weight = pisa[, 13 + i])
#13 + i are the columns for the replicate weights in the data
cfs_i[i, ] &amp;lt;- coef(tmp)
}
&lt;/code>&lt;/pre>
&lt;p>Now &lt;code>cfs_i&lt;/code> has the results from the 80 models. We can inspect this:&lt;/p>
&lt;pre>&lt;code>head(cfs_i)
[,1] [,2] [,3]
[1,] 393.7959 17.95332 -19.58796
[2,] 391.8748 17.85683 -19.90734
[3,] 394.0433 19.00040 -19.70332
[4,] 394.0977 17.96452 -20.31570
[5,] 393.0942 18.24942 -21.16782
[6,] 393.3589 17.99746 -21.55690
&lt;/code>&lt;/pre>
&lt;p>Results will differ per replication. That variability is what allows us
to compute the standard errors. We use the formula that was shown above.
For example, if we want to get the standard error for &lt;code>ESCS&lt;/code> (the second
column in the matrix):&lt;/p>
&lt;pre>&lt;code>sqrt(sum((cfs_i[,2] - cfs[2])^2) * (1 / 20)) #of 1.63
[1] 1.633559
&lt;/code>&lt;/pre>
&lt;p>We can do this all at once though instead of one coefficient at a time:&lt;/p>
&lt;pre>&lt;code>SE &amp;lt;- sqrt(colSums(sweep(cfs_i, 2, cfs, &amp;quot;-&amp;quot;)^2) * (1/20))
data.frame(cfs, SE, t = cfs / SE) #putting it all together
cfs SE t
(Intercept) 392.65420 2.633826 149.081273
ESCS 17.68895 1.633559 10.828471
male -19.97603 2.595143 -7.697468
&lt;/code>&lt;/pre>
&lt;h2 id="example-2-using-the-marksurveymark-package">Example 2: Using the &lt;mark>survey&lt;/mark> package&lt;/h2>
&lt;p>We can just use the &lt;mark>survey&lt;/mark> package and compare results:&lt;/p>
&lt;pre>&lt;code>library(survey)
des &amp;lt;- svrepdesign(
data = pisa,
weights = ~W_FSTUWT,
repweights = dplyr::select(pisa, starts_with(&amp;quot;W_FSTURWT&amp;quot;)),
mse = T,
type = 'Fay',
rho = .5
)
s1 &amp;lt;- svyglm(PV1MATH ~ ESCS + male, design = des)
summary(s1)
Call:
svyglm(formula = PV1MATH ~ ESCS + male, design = des)
Survey design:
svrepdesign.default(data = pisa, weights = ~W_FSTUWT, repweights = dplyr::select(pisa,
starts_with(&amp;quot;W_FSTURWT&amp;quot;)), mse = T, type = &amp;quot;Fay&amp;quot;, rho = 0.5)
Coefficients:
Estimate Std. Error t value Pr(&amp;gt;|t|)
(Intercept) 392.654 2.634 149.081 &amp;lt; 2e-16 ***
ESCS 17.689 1.634 10.828 &amp;lt; 2e-16 ***
male -19.976 2.595 -7.697 3.88e-11 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
(Dispersion parameter for gaussian family taken to be 6846.107)
Number of Fisher Scoring iterations: 2
&lt;/code>&lt;/pre>
&lt;h2 id="example-3-use-the-app-here">Example 3: Use the app here&lt;/h2>
&lt;p>Try this &lt;a href="../2026_repwgt_app/">webapp&lt;/a>. After downloading the csv file
from github, use that and compare results. They are the same.&lt;/p>
&lt;figure>
&lt;img src="alb_res.jpg" alt="Figure 1. Output" />
&lt;figcaption aria-hidden="true">Figure 1. Output&lt;/figcaption>
&lt;/figure>
&lt;p>NOTE: If you were to do this with TIMSS data, this will be slightly
different procedure (the newer TIMSS datasets do not provide the
replicate weights per column but the zone and replication info instead).&lt;/p>
&lt;p>— END&lt;/p></description></item></channel></rss>