Printer randomly moves to home during printing, then resumes as normal
The issue was due to a corrupt SD-card, which was occasionally having some garbage read from it. It turns out that Marlin will try interpret a corrupt move command like G0 X1q3.54 and still read as many numbers as it can. In this example, it would be interpreted as G0 X1 rather than (as might have been intended) G0 X103.54.

This explains my symptoms perfectly:


X and Y always moved to (approximately) their home positions, but it was always only one of them (it's quite unlikely that both moves are corrupted).
Z was not affected because Z moves are much rarer in the G-code (only on layer change) and thus it was very unlikely that a Z move would be affected.
E was not affected since a request to move E to near 0 would be prevented by Marlin's long extrusion prevention.