Skip to content

head()/tail() for emmGrid: follow base-R negative-n semantics#583

Open
SchmidtPaul wants to merge 1 commit into
rvlenth:mainfrom
SchmidtPaul:fix/head-tail-negative-n
Open

head()/tail() for emmGrid: follow base-R negative-n semantics#583
SchmidtPaul wants to merge 1 commit into
rvlenth:mainfrom
SchmidtPaul:fix/head-tail-negative-n

Conversation

@SchmidtPaul

Copy link
Copy Markdown

In base R, head(x, -k) drops the last k elements and tail(x, -k) drops
the first k. The emmGrid methods have these swapped for a negative n:
head.emmGrid(x, -k) drops the first k rows and tail.emmGrid(x, -k) drops the
last k. Positive n is fine.

warp.rg <- ref_grid(lm(breaks ~ wool * tension, data = warpbreaks))  # 6 rows: L L M M H H (tension)

head(1:6, -2)   # base-R reference: 1 2 3 4  (drop last 2)
tail(1:6, -2)   # base-R reference: 3 4 5 6  (drop first 2)

# --- before:
as.character(head(warp.rg, -2)@grid$tension)   # "M" "M" "H" "H"   (dropped the FIRST 2)
as.character(tail(warp.rg, -2)@grid$tension)   # "L" "L" "M" "M"   (dropped the LAST 2)

# --- after:
as.character(head(warp.rg, -2)@grid$tension)   # "L" "L" "M" "M"   (drops the last 2)
as.character(tail(warp.rg, -2)@grid$tension)   # "M" "M" "H" "H"   (drops the first 2)

Fix: rewrote both methods in R/rbind.R to compute the kept-row count exactly
the way utils:::head.default() / tail.default() do — max(N + n, 0L) for a
negative n — using positive indexing only. n = 0 and abs(n) > nrow return
an empty grid, matching base behavior; positive n is unchanged. Present since
the head()/tail() methods were added (commit 3a63e5d, 2022-08-30; first
shipped in 1.8.1); the help page has no negative-n example, so no documented
behavior changes. The only internal callers use positive n, so package
internals are unaffected. Added a regression test in
tests/testthat/test-head-tail.R.

Found via an AI-assisted bug hunt (see #580).

For a negative n, base head(x, -k) drops the last k elements and
tail(x, -k) drops the first k. The emmGrid methods had these swapped:
head.emmGrid(x, -k) dropped the first k rows and tail.emmGrid(x, -k)
dropped the last k. Rewrote both to compute the kept-row count the same
way base R does (positive indexing only). Positive n is unchanged.
Added a regression test.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant