Repository navigation
fix rbind() on loci with a missing allele_ref - #207
JasonAHodgson wants to merge 3 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #207 +/- ##
=======================================
Coverage 93.34% 93.34%
=======================================
Files 133 133
Lines 7920 7922 +2
=======================================
+ Hits 7393 7395 +2
Misses 527 527 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
This looks good. However, can you please move the tests in |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Shared sentinels can incorrectly retain loci with unresolved gaps, leaving missing allele metadata.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Fixes merge failures when allele_ref is missing by normalizing missing alleles before comparison.
Changes:
- Normalizes missing reference alleles.
- Adds regression coverage for missing alleles.
- Documents the fix.
| File | Description |
|---|---|
R/rbind_dry_run.R |
Normalizes missing reference alleles. |
tests/testthat/test_rbind_dry_run.R |
Adds merge regression tests. |
NEWS.md |
Documents corrected behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ref_df$allele_ref[is.na(ref_df$allele_ref)] <- "0" | ||
| target_df$allele_ref[is.na(target_df$allele_ref)] <- "0" |
| unobs_loci_tgt <- cbind(unobs_base_loci, data.frame( | ||
| allele_ref = c("A", "C", "C", "A", "G", "A"), | ||
| allele_alt = c("G", "T", "T", "G", NA, "G") |


Fix
rbind()erroring on a locus whose missing allele is inallele_refThe bug
rbind_dry_run()already guards against this, atR/rbind_dry_run.R:99:but only for
allele_alt.gen_tibble_bed()mapsso a missing allele in the
.bimfile's allele2 column becomes a missingallele_ref, keeps itsNAthroughharmonise_missing_values(), and reaches the==comparisons that buildto_keep_orig.NApropagates,!to_keep_origisNA, and the subscripted assignment fails.The fix
Sanitise both allele columns:
Nothing else changes. Loci with a missing
allele_altare still recovered byresolve_missing_alleles()as before; loci whose gap is inallele_refare nowdropped quietly instead of erroring.
How it came up
Merging HGDP genotyped on the Affymetrix Axiom Human Origins array with 1000
Genomes phase 3. The Axiom
.bimwritesXin the allele2 column for 96 lociwith no observed second allele. Declaring it via the documented route —
— produces an object
rbind()cannot merge.Ordinary
plink --make-bedoutput is mostly unaffected: PLINK writes0in theA1 column, which maps to
allele_altand was always sanitised. So this needs amissing allele specifically in allele2, which is unusual but not exotic.
Tests
tests/testthat/test_missing_alleles.R, six tests over a six-locus fixture:allele_altgap on the ref side, resolvedallele_refgap, dropped not erroredallele_altgap on the target side, resolvedA warning for anyone extending this fixture, which is in a comment at the top of
the file: strand-ambiguous pairs (A/T, C/G) are dropped when
flip_strand = TRUE, and that applies to the alleles after a missing one hasbeen resolved from the other dataset. A pair that looks fine as written can
become ambiguous once repaired, and the locus then disappears for a reason that
has nothing to do with missing data.
Two things noticed but not changed here
resolve_missing_alleles()only inspectsallele_1(i.e.allele_alt),so a gap in
allele_refis dropped even where the other dataset could supplythe allele. Making it consider both columns would recover those loci. Left
out to keep this diff to the crash.
flip()is NA-unsafe.bases == "T"isNAforNAinput, sobases[NA] <- "A"errors. Unreachable now that noNAsurvives to thatpoint, but worth hardening — a lookup (
c(A = "T", T = "A", C = "G", G = "C"))would be NA-safe and shorter, at the cost of needing care to preserve the
documented pass-through of non-ACGT values like
"m".Happy to do either in a follow-up.
Closes #