Ben Bolker's Avatar

Ben Bolker

@bbolker.bsky.social

Ecology, evolution, epidemiology, statistics (mixed models). McMaster University, Hamilton, Ontario https://math.mcmaster.ca/bolker

2,222 Followers  |  590 Following  |  775 Posts  |  Joined: 07.10.2023  |  1.8827

Latest posts by bbolker.bsky.social on Bluesky

The new code can be used with pdfLaTeX or the Unicode engine luaLaTeX. The latter is the preferred engine recommended for new documents.

Agreed. Since we have to do it ourselves I wonder if this is useful: latex3.github.io/tagging-proj... ; github.com/orgs/quarto-... ... looks like the next Quarto release (now at pre-release 1.9) will have some useful stuff? prerelease.quarto.org; github.com/quarto-dev/q...

16.02.2026 19:50 β€” πŸ‘ 0    πŸ” 1    πŸ’¬ 1    πŸ“Œ 0
Image from a 14th c. Italian manuscript of the Inferno in the Bodleian library at Oxford https://digital.bodleian.ox.ac.uk/objects/ab35e336-a471-4cf0-a9a7-592dbb8695d8/surfaces/cba2ff2c-ecd7-44e3-907b-1bd6d0376daf/ : Dante and Virgil are at the right of the image, facing left towards the minotaur who is running down a hill. In this version the head and torso are a man's, the body is the bull's.

Image from a 14th c. Italian manuscript of the Inferno in the Bodleian library at Oxford https://digital.bodleian.ox.ac.uk/objects/ab35e336-a471-4cf0-a9a7-592dbb8695d8/surfaces/cba2ff2c-ecd7-44e3-907b-1bd6d0376daf/ : Dante and Virgil are at the right of the image, facing left towards the minotaur who is running down a hill. In this version the head and torso are a man's, the body is the bull's.

Did you know there was some confusion during the Medieval and Renaissance periods about which end of the Minotaur was bullish and which was manly?

scifi.stackexchange.com/a/294815/35859

13.02.2026 21:13 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 2    πŸ“Œ 0
R.I.P., John Fox - Yihui Xie | θ°’η›ŠθΎ‰ Last November, I learned the very sad news from Michael Friendly that John Fox had passed away. That brought my memory back to 2006 when I emailed John for the first time asking for his help on a &hel...

#rstats RIP, John Fox
@yihui.org just published this lovely tribute to John Fox and his work

yihui.org/en/2026/02/j...

12.02.2026 02:05 β€” πŸ‘ 20    πŸ” 5    πŸ’¬ 0    πŸ“Œ 0

Has anyone tried vibe (LLM) translating Matlab to Julia? How did it go?

09.02.2026 20:56 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

that's @gsimpson.bsky.social , @noamross.net , @ericjpedersen.bsky.social , and fediscience.org/@millerdl@ma... looking down from the top of the heap, right?

03.02.2026 16:39 β€” πŸ‘ 6    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
GitHub - EmilHvitfeldt/quarto-revealjs-editable: Repositioning and resizing of images and text directly in quarto revealjs slides Repositioning and resizing of images and text directly in quarto revealjs slides - GitHub - EmilHvitfeldt/quarto-revealjs-editable: Repositioning and resizing of images and text directly in quarto...

I was going to ask someone to remind me of the magic "resize quarto figures interactively, then insert the figure size parameters back into the quarto document" plug-in; I managed to find it, so here it is again for anyone who didn't hear about it the first time: github.com/EmilHvitfeld...

02.02.2026 23:11 β€” πŸ‘ 20    πŸ” 4    πŸ’¬ 1    πŸ“Œ 1

What's the best open book for data science from a base-R perspective? #rstats

02.02.2026 17:19 β€” πŸ‘ 9    πŸ” 6    πŸ’¬ 8    πŸ“Œ 0
Phylogenetic random effects

PS you should also check out the capabilities of the `gllvm` package: cran.r-project.org/web/packages... @vdveenb.bsky.social

29.01.2026 00:07 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
Preview
udm14 – Get this Extension for 🦊 Firefox (en-CA) Download udm14 for Firefox. Adds a Google search engine that includes the udm=14 parameter

for lazy Firefox users like me who want to suppress Google's AI responses to search with the least amount of effort ... addons.mozilla.org/en-CA/firefo... (I didn't count, but I think it was fewer than 5 mouse clicks)

28.01.2026 23:06 β€” πŸ‘ 5    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
GLMMs in RTMB

If someone is feeling a bit ambitious :-) a basic version of this could be hacked up in RTMB ... see bbolker.github.io/bbmisc/rtmb_...

28.01.2026 23:04 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Multivariate modeling via mixed models

Not yet ... if all of your variables are of the same type (e.g. Gaussian, Poisson, etc.) you can do it by "melting" the data into long format, e.g. mac-theobio.github.io/QMEE/lecture... . Multi-type models are technically fairly straightforward; the hard part is the user interface ...

28.01.2026 22:59 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 2    πŸ“Œ 0
datamint.ing

check it out: datamint.ing

28.01.2026 18:30 β€” πŸ‘ 0    πŸ” 1    πŸ’¬ 0    πŸ“Œ 0

the heavy-metal ΓΌmlaut and the New Yorker diΓ«resis (yes, I know ...)

27.01.2026 17:46 β€” πŸ‘ 2    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
OpenAlex

I think openalex.org is trying to get there ... although I feel like it's being used more for bibliometrics ... ?

26.01.2026 21:09 β€” πŸ‘ 5    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Preview
Can we put some operators at the beginning of lines? Β· Issue #29 Β· posit-dev/air There is a very popular issue in prettier about putting the operators of multiline binary expressions at the beginning of lines prettier/prettier#3806 Lots of languages do prefer operators at the b...

oh well: github.com/posit-dev/ai...

26.01.2026 13:11 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 0    πŸ“Œ 1

but wait, what about placement on premium squares (double/triple {letter, word} scores) ... ? @stephenbheard.bsky.social

26.01.2026 12:57 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

following your last example: do people use phylogenetic information in their predictive models of mushroom toxicity ... ??

26.01.2026 01:14 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Left panel, a salt shaker containing multiple pepper packets, labeled 'x'. Middle, shaker containing one packet, labeled 'x[0:1]'. Right, top, one pepper packet, labeled 'x[0]'. Right, bottom, pile of pepper grains, labeled 'x[0][0]'

Left panel, a salt shaker containing multiple pepper packets, labeled 'x'. Middle, shaker containing one packet, labeled 'x[0:1]'. Right, top, one pepper packet, labeled 'x[0]'. Right, bottom, pile of pepper grains, labeled 'x[0][0]'

BTW, I got confused: the picture in the thread above is @hadley.nz's original R version. I made this Python version at some point.

24.01.2026 15:28 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

R was written in the 1990s by statisticians; its development model is conservative; & 64-bit integers are well implemented in the `bit64` package (which the OP is using). Things only get weird in edge cases. For performant code outside R's usual scope you're prob interfacing with C++/Rust anyway.

23.01.2026 23:51 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
What’s happening?


dd[["x"]] and dd$x return the vector integer64, so sum() dispatches to bit64’s method for the Summary group generics (sum.integer64), which knows how to add 64‑bit integers correctly. Result: 55 βœ…


dd["x"] returns a one-column data.frame (i.e., a list). When you call sum(dd["x"]), you’re now calling sum() on a data.frame, not on an integer64 vector.
For data.frames, base R uses the Summary group generic method Summary.data.frame (in base). Internally, this method coerces the data frame to something vector-like (e.g., via as.matrix() or unlist() pathways) before applying the sum generic. In doing so, it strips the integer64 class, and the remaining underlying storage is misinterpreted.


integer64 (from bit64) is not a native R type; it’s a classed vector with an underlying storage that does not map 1:1 to base numeric types. When the class is stripped by the data.frame method, the bytes get reinterpreted (e.g., as doubles) instead of being properly converted. That’s why you see a tiny, nonsensical denormal-like value such as 2.717361e-322 β€” it’s the result of interpreting the 64‑bit integer bits as an IEEE-754 double, not the sum of actual numbers.

What’s happening? dd[["x"]] and dd$x return the vector integer64, so sum() dispatches to bit64’s method for the Summary group generics (sum.integer64), which knows how to add 64‑bit integers correctly. Result: 55 βœ… dd["x"] returns a one-column data.frame (i.e., a list). When you call sum(dd["x"]), you’re now calling sum() on a data.frame, not on an integer64 vector. For data.frames, base R uses the Summary group generic method Summary.data.frame (in base). Internally, this method coerces the data frame to something vector-like (e.g., via as.matrix() or unlist() pathways) before applying the sum generic. In doing so, it strips the integer64 class, and the remaining underlying storage is misinterpreted. integer64 (from bit64) is not a native R type; it’s a classed vector with an underlying storage that does not map 1:1 to base numeric types. When the class is stripped by the data.frame method, the bytes get reinterpreted (e.g., as doubles) instead of being properly converted. That’s why you see a tiny, nonsensical denormal-like value such as 2.717361e-322 β€” it’s the result of interpreting the 64‑bit integer bits as an IEEE-754 double, not the sum of actual numbers.

MS Copilot (ugh) gives a useful answer here, if you ask it carefully:

23.01.2026 22:37 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Seems to be here, but I'm not sure I understand what's going on: github.com/wch/r-source... (in any case the tl;dr is "use double brackets")

23.01.2026 22:12 β€” πŸ‘ 4    πŸ” 1    πŸ’¬ 1    πŸ“Œ 0

(2/3) as for why `sum(list(<integer>))` returns a sensible answer and `sum(list(<int64>))` doesn't, I think that would require some digging into the guts: `sum` is `function (..., na.rm = FALSE) .Primitive("sum")`, which means going into the C code, e.g. `pryr::show_c_source(.Primitive("sum"))`

23.01.2026 22:12 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
> library(bit64)

> dd <- data.frame(x = as.integer64(1:10), y = as.integer(1:10))

> sum(dd$x)
integer64
[1] 55

> sum(dd["x"])
[1] 2.717361e-322

> sum(dd[["x"]])
integer64
[1] 55

> sum(dd$y)
[1] 55

> sum(dd["y"])
[1] 55

> sum(dd[["y"]])
[1] 55
>

> library(bit64) > dd <- data.frame(x = as.integer64(1:10), y = as.integer(1:10)) > sum(dd$x) integer64 [1] 55 > sum(dd["x"]) [1] 2.717361e-322 > sum(dd[["x"]]) integer64 [1] 55 > sum(dd$y) [1] 55 > sum(dd["y"]) [1] 55 > sum(dd[["y"]]) [1] 55 >

A multi-panel figure. Left: 'x'; a pepper-shaker containing a collection of paper packets of pepper. Middle: 'x[1]': a pepper-shaker containing a single pepper packet; Right, top: 'x[[1]]': a single pepper packet; Right, bottom: 'x[[1]][[1]]': a pile of grains of pepper

A multi-panel figure. Left: 'x'; a pepper-shaker containing a collection of paper packets of pepper. Middle: 'x[1]': a pepper-shaker containing a single pepper packet; Right, top: 'x[[1]]': a single pepper packet; Right, bottom: 'x[[1]][[1]]': a pile of grains of pepper

(1/2) It's definitely the interaction of single-brackets and integer64. Single square brackets return a list, double square brackets (generally safer/best practice!) return a vector. (Left-hand image is a modified version of a Python original by @hadley.nz, I think.).

23.01.2026 22:06 β€” πŸ‘ 5    πŸ” 0    πŸ’¬ 3    πŸ“Œ 0

Starship Troopers: 1959. Forever War: +15 years (1974). Old Man's War: +31 years (2005). Present: +21 years.

21.01.2026 17:43 β€” πŸ‘ 8    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

Through an understanding of the ecophysiological and biochemical mechanisms of adaptation that describe the potential for a plant to persist in a habitat or location, one can better assess the impact of an altered environment on future plant performance and restoration outcomes. [yikes!]

21.01.2026 16:16 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0
grepv("^c", rownames(installed.packages())) |> Filter(f = \(x) x %in% qdap::GradyAugmented)

grepv("^c", rownames(installed.packages())) |> Filter(f = \(x) x %in% qdap::GradyAugmented)

annals of yak shaving: troubling remembering the name of the amazing github.com/cynkra/const... pkg (human-readable `dput()`). I remember (1) I have it installed (2) the names starts with "c" and (3) is an English word ...

20.01.2026 19:07 β€” πŸ‘ 1    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Hmm. What's the rationale for using group_by/summarize/ungroup with collabs? I'm trying to switch to `.by` and especially trying to teach with `.by`: shorter, safer [leftover groupings can cause problems]); cases where you want to `group_by()` to do several operations in a row are rarer ...

20.01.2026 15:41 β€” πŸ‘ 3    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0
Writing R Extensions Writing R Extensions

This has to do w/ whether `LazyData` is set cran.r-project.org/doc/manuals/... 1.1.6:

The data subdir is for data files, either to be made available via lazy-loading or for loading using data(). (The choice is made by the β€˜LazyData’ field in the DESCRIPTION file: the default is not to do so.)

19.01.2026 16:20 β€” πŸ‘ 4    πŸ” 0    πŸ’¬ 0    πŸ“Œ 0

Anyone have a good resource in comparing bootstrapping and permutation testing? They both do some resampling, but their philosophies are very different.

15.01.2026 18:11 β€” πŸ‘ 5    πŸ” 3    πŸ’¬ 2    πŸ“Œ 0
R code

library(microbenchmark); library(ggplot2)
set.seed(1001)
n <- runif(1e6, 0, 2)
m1 <- microbenchmark(
  pmax(n,1),
  pmax.int(n,1),
  {n[n<1] <- 1}
)
autoplot(m1)

R code library(microbenchmark); library(ggplot2) set.seed(1001) n <- runif(1e6, 0, 2) m1 <- microbenchmark( pmax(n,1), pmax.int(n,1), {n[n<1] <- 1} ) autoplot(m1)

A 'microbenchmark' plot of pmax(), pmax.int(), and n[n<1] <- 1 as in the previous code. medians are pretty close together, bulk of the results are between 1.5 and 3 milliseconds for all three methods. maxima are larger (longer tail) for pmax.int and sub-assignment

A 'microbenchmark' plot of pmax(), pmax.int(), and n[n<1] <- 1 as in the previous code. medians are pretty close together, bulk of the results are between 1.5 and 3 milliseconds for all three methods. maxima are larger (longer tail) for pmax.int and sub-assignment

Hmm, I'm not seeing much difference. What am I missing?

12.01.2026 23:12 β€” πŸ‘ 0    πŸ” 0    πŸ’¬ 1    πŸ“Œ 0

@bbolker is following 20 prominent accounts