Sign in

tj mahr 🤘

@tjmahr.com
2.7K followers 1K following 6K posts

data scientist studying how kids learn to speak, dad, jump roper, bayesian, husband to @amandawalrus.bsky.social, tjmahr.com, Madison, WI

PostsRepliesMedia
tj mahr 🤘 @tjmahr.com · 05/10/2026
scrambled to get into position for the postworkout clip feature
000
tj mahr 🤘 @tjmahr.com · 04/10/2026
Fact, value. Value, fact. FACT, VALUE.
brandAn is good @LeBearGirdle
[Dentist waiting room]
Me: [chanting] teeth, teeth-
Other patients: teeth, TEETH
Secretary: [pounding her clipboard] TEETH, TEETH, TEETH!
3:30 PM • 17 Aug 17 • Twitter for Android
40.4K Retweets 120K Likes
1120
tj mahr 🤘 @tjmahr.com · 03/10/2026
my kid won a homecoming color contest and she got to be in the parade and on the field at halftime during the game @uwmadison.bsky.social
0110
tj mahr 🤘 @tjmahr.com · 02/10/2026
another week another SPRAWLING EXEGESIS
screenshot of several pages of a word doc describing an analysis
030
tj mahr 🤘 @tjmahr.com · 02/10/2026
oh right. i never noticed while listening to the album but the song popped up on shuffle so the reprise startled me
5. "I Believe"
6. "Broken"
7. "Head over Heels/Broken (Live)"
8. "Listen"
110
tj mahr 🤘 @tjmahr.com · 01/10/2026
a lil spline factoid to cram in your brainpan

Because of the smoothing terms, the intercept is not interpretable as a
baseline intelligibility at any given age. The intercept is
approximately the average logit-scale intelligibility value across all
*observed* ages. I emphasize the word *observed* because we weight by
the frequency of the ages. Instead of make a prediction at each of the 
unique ages, we make a prediction at each observed age (including repeats) and 
average them together. For example,

```{r}
intercept_draws <- model_single$data |> 
  # Set all of categorical variables to their reference levels
  mutate(type = "nonparent", otype = "nonparent"
  ) |> 
  # Make fixed-effects prediction
  posterior_linpred(model_single, newdata = _, re_form = NA) |> 
  # Average over them
  rowMeans()

intercept_draws_from_model <- model_single |> 
  as_draws_df(variable = "b_Intercept") |> 
  pull("b_Intercept")

all.equal(intercept_draws, intercept_draws_from_model)
```
060
tj mahr 🤘 @tjmahr.com · 01/10/2026
sorry my jumprope app added a video thing and i am eager to try it
150
tj mahr 🤘 @tjmahr.com · 30/09/2026
wat
microsoft word cannot save my document bc the C drive is full
100
tj mahr 🤘 @tjmahr.com · 30/09/2026
sentenced by reviewer 1 to writing another one of these things
Our inferential goal was estimation the pertinent estimands for the research questions describe above. That is, we want to determine the sign (direction) and magnitude (size) of relevant effects, and we want to characterize our uncertainty about those effects. We performed estimation by proposing a data-generating process (a model) for the observed data. This model is controlled by unobserved statistical parameters and we learn plausible values for the parameters by conditioning (or training) the model on the observations. Because the model is generative, predictions from the model are estimates, so simulating and averaging over predictions from a model provides a direct way to perform statistical inference on the outcome scale of the data (Gelman and Hill, 2006). 
Under a Bayesian framework, we provide some initial information about the model parameters in the form of prior distributions. We can think of the priors as providing the requisite information needed to simulate observations from the model before (prior to) seeing any data. We can also think of priors as providing penalties on extreme effects. (Simpson paper on types of priors) We used the latter “weakly informative” priors for this analysis. After conditioning on the data, we obtain the posterior distribution for the model parameters. In practice, a Bayesian model contains of a sample of posterior parameter draws where each draw represents a set of parameter values are that plausible given the data and prior information. Because each draw represents a plausible set of parameter values, a prediction based on those parameters is also a plausible prediction, so we can obtain a posterior distribution of predictions. Thus, these posterior draws make it straightforward to quantify the uncertainty around a statistical estimate and propagate that uncertainty through other downstream estimates or contrasts (such as the difference into growth curves).
5120
tj mahr 🤘 @tjmahr.com · 30/09/2026
That mostly looks like a negative correlation plus random other dots
Infographic slop from Facebook.
040
tj mahr 🤘 @tjmahr.com · 30/09/2026
good ol Facebook, making bayes theorem as confusing as possible
Infographic explainer of the medical testing version of bayes theorem
4100
tj mahr 🤘 @tjmahr.com · 29/09/2026
seething rn. thanks for the heads up
photo of my empty spare tire area
121
tj mahr 🤘 @tjmahr.com · 29/09/2026
lol
@Joschua_Bo • 2y ago (edited)
This comment section is now like angry zoo visitors who aren't able to spot the promised angry italians
020
tj mahr 🤘 @tjmahr.com · 29/09/2026
some early cartridges of Super Mario Bros 3 are “Left Bros” cartridges because they put the word “Bros” in a goofy ass position on the left and later productions moved it to the more sensible position on the right. The more you know 💫
Left BrosRight Bros
160
tj mahr 🤘 @tjmahr.com · 25/09/2026
look at this beast
screenshot of page thumbnails for supplement materials document
3161
tj mahr 🤘 @tjmahr.com · 23/09/2026
you fought in the Pipe Wars?
1132
tj mahr 🤘 @tjmahr.com · 23/09/2026
lil brms rmarkdown tip v <- list() # brms gives you these v$brms <- model$version$brms v$cmdstanr <- model$version$cmdstanr v$stan <- model$version$stan v$rstan <- model$version$rstan # close enough v$r <- getRversion() # but i should be stashing the R version inside the model object

## Software details

Analyses were conducted in the R programming language [vers. `r v$r`,
@r-base]. Models were fit using the Stan programming language
[vers. `r v$stan`, @stan-base] via the brms
[vers. `r v$brms`, @brms2017] and cmdstanr [vers. `r v$cmdstanr`,
@r-cmdstanr] R packages. Handling the posterior samples
was greatly simplified by the posterior [vers. `r v$posterior`,
@r-posterior] and ggdist [vers. `r v$ggdist`, @ggdist2024] R packages.
021
tj mahr 🤘 @tjmahr.com · 21/09/2026
*tears in my eyes*
4222
tj mahr 🤘 @tjmahr.com · 19/09/2026
SO I FORMATTED MY
MEME LIKE THIS
Which was the style at the time
0291
tj mahr 🤘 @tjmahr.com · 18/09/2026
some real sicko stuff here
r code where i simulate new xs from a mixed effects model and then feed them as predictors into another mixed effects model
130
tj mahr 🤘 @tjmahr.com · 17/09/2026
i was obsessed with this one way way back when
dear athetits
if GOD dont exist s

(shiba inu wearing a tin foil hat)

how me a dog learned english?
021
tj mahr 🤘 @tjmahr.com · 17/09/2026
hell yeah
plot showing delta x and delta y for observed and simulated data
020
tj mahr 🤘 @tjmahr.com · 17/09/2026
how position legend in the top left of plot
250
tj mahr 🤘 @tjmahr.com · 17/09/2026
re-creation of a funny lil bug from a bad autocompletion i ran into today
2100
tj mahr 🤘 @tjmahr.com · 15/09/2026
the most consequential figures in the tech world are half guys like steve jobs and bill gates and half some guy named ronald who maintains a unix tool called 'runk' which stands for Ronald's Universal Number Kounter and handles all math for every machine on earth
1261
tj mahr 🤘 @tjmahr.com · 14/09/2026
magnets are still the best stud finders
My flying pig with a magnet nose toy stuck to my wall
050
tj mahr 🤘 @tjmahr.com · 11/09/2026
bringing a certain craft to my write-ups lol
 
Figure 3. .
Again, we see that productions with above-average scores receive lower expected ratings. Are we seeing an interaction effect? Maybe. The posterior median line of the POST line starts higher and ends lower than the TX line, so the relationship in that condition is visually steeper. But these visual slopes on the expected ratings do not neatly correspond to any model parameters.
If we fixate on x = 0, we see vertical separation between the PRE line and the TX and POST lines. That is, tokens with average nF3F2_z values within a speaker had higher expected ratings in the TX and POST treatment conditions. We can compute this vertical differences at x = 0:
data_draws_expectations |> 
  filter(nf3f2_z_wi == 0) |> 
  tidybayes::compare_levels(.epred, fphase) |> 
  ggdist::median_qi() |> 
  select(-nf3f2_z_wi)
#> # A tibble: 3 × 8
#>   fphase     id    .epred .lower .upper .width .point .interval
#>   <chr>      <chr>  <dbl>  <dbl>  <dbl>  <dbl> <chr>  <chr>    
#> 1 POST - PRE fake   0.674  0.194  1.10    0.95 median qi       
#> 2 POST - TX  fake  -0.111 -0.588  0.363   0.95 median qi       
#> 3 TX - PRE   fake   0.782  0.287  1.21    0.95 median qi
We might conclude, on the basis of this comparison, that some amount of perceptually salient improvement in /r/ production occurred but it was not captured by the nF3F2 values. But there’s a problem. It doesn’t make sense to compare treatment phases with a speaker’s across-phase average nF3F2_z if we think that treatment phase affects nF3F2_z scores. (We do, of course, because we think changes in perceptual ratings should be accompanied by commensurate changes in speech acoustics.) That brings us to the other part of the multivariate model.
010
tj mahr 🤘 @tjmahr.com · 10/09/2026
why do i get soooo didactic
screenshot from supplemental materials 

 
Model intuition.
The four thresholds between rating levels are intercept terms in the model, and they represent represent the log-odds of a rating of k or less. For example, the third intercept term is the threshold 3|4 (between ratings 3 and 4), and it is the log-odds of receiving a 3, 2 or 1 rating (i.e., the scores to the left of the threshold). If we convert these logodds to probabilities, we can recover the probabilities of an individual rating. That is, the probability of a 3 is P(3 or less) - P(2 or less).
Below shows the direct computation of the rating probabilities from the model’s fixed effects:
model_nf3f2 |> 
  as_draws_df() |> 
  select_variables(matches("b_ord.*Intercept")) |> 
  posterior::mutate_variables(
    thresh21 = `b_ordrating_Intercept[1]`,
    thresh32 = `b_ordrating_Intercept[2]`,
    thresh43 = `b_ordrating_Intercept[3]`,
    thresh54 = `b_ordrating_Intercept[4]`,
    prob_of_1 = plogis(thresh21),
    prob_of_2 = plogis(thresh32) - plogis(thresh21),
    prob_of_3 = plogis(thresh43) - plogis(thresh32),
    prob_of_4 = plogis(thresh54) - plogis(thresh43),
    prob_of_5 = 1 - plogis(thresh54)
  ) |> 
  select_variables(starts_with("thresh"), starts_with("prob")) |> 
  posterior::summarise_draws()
#> Loading required namespace: rstan
#> # A tibble: 9 × 10
#>   variable    mean median     sd     mad      q5    q95  rhat ess_bulk
#>   <chr>      <dbl>  <dbl>  <dbl>   <dbl>   <dbl>  <dbl> <dbl>    <dbl>
#> 1 thresh21  -1.45  -1.44  0.275  0.267   -1.90   -0.996  1.00    1186.
#> 2 thresh32  -0.324 -0.319 0.274  0.266   -0.767   0.134  1.00    1185.
#> 3 thresh43   0.744  0.748 0.275  0.264    0.297   1.20   1.00    1189.
#> 4 thresh54   1.96   1.97  0.275  0.264    1.51    2.42   1.00    1188.
#> 5 prob_of_1  0.194  0.191 0.0431 0.0410   0.131   0.270  1.00    1186.
#> 6 prob_of_2  0.227  0.229 0.0238 0.0234   0.185   0.263  1.00    1239.
#> 7 prob_of_3  0.254  0.256 0.0103 0.00750  0.235   0.266  1.00 …
391
tj mahr 🤘 @tjmahr.com · 10/09/2026
i'm like not a mediation guy btw
  To connect to the other literature, our analysis is a flavor of a 1-1-1 mediation analysis (Bauer et al., 2006). We have three variables and we want to study how the influence of one “flows through” another (the mediation part), and the effects of interest are random within-participant effects (the 1-1-1 part). Indeed, we want to know whether a big treatment effect on a participant’s normalized F3-F2 values translates to a big treatment effect on their PRS rating scores. Yet, I say “flavor of a 1-1-1 mediation analysis” because I did not come upon Bauer et al. (2006) or its terminology until after developing this model. The main sources for model development were Richard’s McElreath’s Latent Mundlak Machine https://www.youtube.com/watch?v=iwVqiiXYeC4&t=3299s and the within-between decomposition framework by Hoffman & Walters (2022).
000
tj mahr 🤘 @tjmahr.com · 10/09/2026
is this := important?
For example:

library(S7)
NComponents := new_class(properties = list(n = property_scalar(S7::class_integer)))

n_comps <- NComponents(5L)
n_comps
100
tj mahr 🤘 @tjmahr.com · 09/09/2026
making progress
1140
tj mahr 🤘 @tjmahr.com · 09/09/2026
when should an automatic tool-tip go away?
120
tj mahr 🤘 @tjmahr.com · 08/09/2026
My yard cow in between a stained and unstained section of fence
040
tj mahr 🤘 @tjmahr.com · 04/09/2026
gotta rep the DARE here
screenshot of the dictionary of american regional english map for "tree lawn"
110
tj mahr 🤘 @tjmahr.com · 04/09/2026
i don't think there is going to be a new markdown flavor, based on what copilot read in the q2/claude-notes/ folder. do you know about knitr::convert_chunk_header() btw?
do there seem to be changes in the qmd file format as a result of the port to rust?

I'll examine the claude-notes folder to see if there are any notes about changes in the qmd file format resulting from the port to Rust.

Let me check what's in the folder:

Let me check the main Rust porting summary document which should cover file format changes:

Based on the comprehensive Rust porting study in the claude-notes, there are no significant format changes to the .qmd (Quarto Markdown) file format as a result of the port to Rust. Here's why:
Key Points:
1. Parser Already Exists in Rust

The quarto-markdown parser is already implemented in Rust (~11K LOC). This means the Rust version uses the same grammar and parsing logic as the original. The parser converts QMD files to typed Pandoc AST with full source tracking—same as before.
2. Format is Language-Agnostic

The .qmd file format is fundamentally a markup language specification (CommonMark + Quarto extensions). The format itself is independent of implementation language—Rust and TypeScript both parse the same syntax.
3. Source Tracking Enhancement (Not Format Change)

The main innovation mentioned is improved source location tracking through the port. The study discusses MappedString/SourceInfo infrastructure to track positions through transformations. This is an internal implementation detail that doesn't affect the file format itself—it just makes error reporting more accurate.
4. YAML Frontmatter Unchanged

The YAML metadata system remains the same. The port includes detailed analysis of YAML parsing and validation, but the schema and format of YAML frontmatter in .qmd files stays consistent.
100
tj mahr 🤘 @tjmahr.com · 04/09/2026
just like a cat brings its owner some unfortunate dead animal as a present, I bring you a screenshot from Facebook
I think some of you are looking at this the wrong way. One die is rolled three times. Assuming it is six-sided, with a five only on one of those six sides, there is a 1 in 6 chance EACH ROLL of a getting a five. Doing that three times gives you 1/6+1/6+1/6 chance of a five - which totals
3/6..or 50%.
1140
tj mahr 🤘 @tjmahr.com · 03/09/2026
making my knitr hook for running downlit also include the original markdown output in an html comment so that the .md file is still legible. surely, nothing bad will happen from this hacker
screenshot of a git diff that shows the markdown output wrapped in a comment
020
tj mahr 🤘 @tjmahr.com · 03/09/2026
I was cleaning my fence and feeling discouraged by how the wood turned green in a few areas and then duh
I was wearing green tinted safety glasses
2160
tj mahr 🤘 @tjmahr.com · 01/09/2026
Ponies are shorter than 14.2 hands which is actually 14 1/2 hands because the fractional part is in base four, because of horse it is
It may be abbreviated to
"h" or "hh" 131 Although measurements between whole hands are usually expressed in what appears to be decimal format, the subdivision of the hand is not decimal but is in base 4, so subdivisions after the radix point are in quarters of a hand, which are inches.!2) Thus, 62 inches is fifteen and a half hands, or 15.2 hh (normally said as "fifteen-two" , or occasionally in full as "fifteen
hands two inches"). [2]
140
tj mahr 🤘 @tjmahr.com · 25/08/2026
annoyed this never occurred to me. (it's a method for bootstrapping repeated measures data. text via Deen & de Rooij, 2020, doi.org/10.3758/s134...)
Balanced bootstrap  The balanced bootstrap can be used to ensure that every individual appears exactly B times in the bootstrap samples, in contrast to randomly drawing bootstrap samples from the parent sample. Davison and Hinkley (1997) show that the balanced bootstrap results in an efficiency gain.  For unbalanced longitudinal data, where some subjects have more measurements than others, the balanced bootstrap ensures that the average size of the bootstrap samples equals the (subject) sample size N. In the balanced bootstrap, rather than simply drawing at random, a matrix is made with B copies of the numbers 1 to N. This matrix is vectorized, randomly shuffled, and turned back into a matrix of size N × B (Gleason, 1988). Each of the columns of this latter matrix gives the indices of a single bootstrap sample.
2306
tj mahr 🤘 @tjmahr.com · 22/08/2026
finally making some progress on my double under crosses (one jump, cross/uncross arms, rope goes under you twice)
230
tj mahr 🤘 @tjmahr.com · 21/08/2026
I was making dinner when I listened to the talk but took a screenshot of this slide bc I want to spent an hour of self-study unpacking it and want to able to throw around the word “isotropic”
Screenshot of the slide about an orthonormal basis
3130
tj mahr 🤘 @tjmahr.com · 18/08/2026
spinning the rope with arms crossed is awkward and not very cool looking but I figured I should develop the skill at this point.
61073
tj mahr 🤘 @tjmahr.com · 17/08/2026
🔀🔀🔀
160
tj mahr 🤘 @tjmahr.com · 16/08/2026
(iOS) just search settings for “offload”
Screenshot of the search
010
tj mahr 🤘 @tjmahr.com · 14/08/2026
Instagram just feeding me weird music and I’m not complaining
Lately you've been into discovering new artists, nostalgic rock vibes and navigating parenthood.
000
tj mahr 🤘 @tjmahr.com · 13/08/2026
New York City looks so good in the movie. You could say it’s like another character in the movie
010
tj mahr 🤘 @tjmahr.com · 12/08/2026
as you can, "strike" is sometimes pronounced "stee-rike" before the words 'one', 'two', 'three'
screenshot of r code/results

> results |> 
+   bind_rows() |> 
+   filter(stringr::str_detect(note, "after|before|\\bat the")) |> 
+   distinct(word, note, enpr, ipa)
               word                                                         note          enpr               ipa
1               the                                  weak form before consonants          <NA>              /ðə/
2               the                                  weak form before consonants           thə              <NA>
3               the                                      weak form before vowels          <NA>        /ði/ [ðɪj]
4               the                                      weak form before vowels           thē              <NA>
5               the                                      weak form before vowels          <NA>              /ðə/
6               the                                      weak form before vowels           thə              <NA>
7               one                      at the end of sentences, before a pause          <NA> [wɐn(˦˧)~wän(˦˧)]
8           Réunion                                                 after French          <NA>     /ɹeɪ.uːniˈɒn/
9             sixth                       common reduced form before a consonant          <NA>            [sɪks]
10               of                                           before a consonant          <NA>               /ə/
11               to                                           before a consonant          <NA>              /tə/
12               to                                           before a consonant          <NA>              /tʊ/
13               to                                                after a vowel          <NA>              [ɾə]
14               to                                                after a vowel          <NA>           [ɾʊ(w)]
15               to                                                after a vowel          <NA>              [ɾu̟]
16               ag    …
010
tj mahr 🤘 @tjmahr.com · 12/08/2026
R output of the entries with "weak for" in the pronunciation note

> results |> 
+   bind_rows() |> 
+   filter(stringr::str_detect(note, "weak form")) |> 
+   distinct(word) |> 
+   pull(word) |> 
+   sort() |> 
+   dput()
c("am", "another", "are", "as", "because", "can", "could", "do", 
"does", "for", "go", "had", "have to", "him", "in", "must", "myself", 
"myselves", "or", "our", "shall", "should", "that", "that's", 
"the", "there", "there's", "til", "us", "was", "were", "would", 
"yourself", "yourselves")
> results |> 
+   bind_rows() |> 
+   filter(stringr::str_detect(note, "strong")) |> 
+   distinct(word) |> 
+   pull(word) |> 
+   sort() |> 
+   dput()
c("am", "amen", "another", "are", "as", "because", "could", "do", 
"does", "for", "had", "have to", "him", "in", "must", "myself", 
"myselves", "or", "our", "shall", "should", "that", "the", "there", 
"there's", "us", "was", "were", "would", "yourself", "yourselves"
)
100
tj mahr 🤘 @tjmahr.com · 12/08/2026
i'll just download the dictionary then
screenshot showing an R data.frame of all the wiktionary pronunciations for "for" in the last post
220