Skip to content

feat: add factor_level_method, factor_as_factor, factor_level_last_pattern to df_explicit_na#1487

Merged
shajoezhu merged 9 commits into
insightsengineering:mainfrom
kaipingyang:feature/df-explicit-na-factor-level-method
Jul 13, 2026
Merged

feat: add factor_level_method, factor_as_factor, factor_level_last_pattern to df_explicit_na#1487
shajoezhu merged 9 commits into
insightsengineering:mainfrom
kaipingyang:feature/df-explicit-na-factor-level-method

Conversation

@kaipingyang

@kaipingyang kaipingyang commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds three new arguments to df_explicit_na() to give users control over factor level ordering. Motivated by #1322.

New arguments

  • factor_level_method ("sort_auto" / "sort_radix" / "data") — controls how levels are ordered when character or logical columns are converted to factors (or existing factors are re-encoded via factor_as_factor):

    • "sort_auto" (default): sort(unique(x)) — locale-aware, identical to the original behaviour. No existing code is affected.
    • "sort_radix": sort(unique(x), method = "radix") — byte-order (ASCII) sort, not locale-sensitive. Uppercase letters always sort before lowercase, which matches the behaviour of SAS PROC SORT on mixed-case data.
    • "data": unique(x) — levels follow first-appearance order in the data.
  • factor_as_factor (FALSE by default) — when TRUE, existing factor columns are also re-encoded using factor_level_method. The default FALSE preserves the original behaviour (existing factor levels are kept as-is).

  • factor_level_last_pattern (NULL by default) — a regular expression; any levels matching it are moved to the end of the level list, immediately before na_level. Useful for consistently placing catch-all categories (e.g. "Other", "Unknown") last. Has no effect when NULL.

Backward compatibility

All three arguments have defaults that exactly reproduce the original function behaviour, so no existing code needs to change.

Test plan

  • factor_level_method = "sort_auto" produces identical results to the unmodified function
  • factor_level_method = "sort_radix" sorts uppercase before lowercase on mixed-case data
  • factor_level_method = "data" preserves first-appearance order
  • factor_as_factor = TRUE re-encodes existing factor levels; FALSE leaves them unchanged
  • factor_level_last_pattern moves matching levels to end; NULL is a no-op
  • na_level remains the last level in all cases
  • Input validation errors for invalid argument types

Fixes #1322

…ttern to df_explicit_na

- factor_level_method: controls level ordering (sort_auto/sort_radix/data)
  sort_auto preserves original behaviour; sort_radix uses byte-order (ASCII)
  sort which is not locale-sensitive; data uses first-appearance order
- factor_as_factor: when TRUE, re-encodes existing factor columns via
  factor_level_method (default FALSE preserves original behaviour)
- factor_level_last_pattern: regex to move matching levels to end before
  na_level; NULL by default (no effect); only applies during re-encoding

Closes insightsengineering#1322

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

✅ All contributors have signed the CLA
Posted by the CLA Assistant Lite bot.

@shajoezhu

Copy link
Copy Markdown
Contributor

brilliant! @kaipingyang great to see you here!

@kaipingyang

Copy link
Copy Markdown
Contributor Author

brilliant! @kaipingyang great to see you here!

Thanks! Happy to address any review comments.

@Melkiades Melkiades left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, this is a nice feature and the defaults do reproduce the old behaviour (checked, output is byte-identical to main across char/logical/factor inputs). a few things before merge:

  • the sort_radix test fails under LC_COLLATE=C, which is what testthat edition 3 forces via local_reproducible_output(). under C collate sort_auto is already byte-order so it equals radix and expect_false(identical(...)) fails. it only passes locally because your shell is en_US.UTF-8. drop that line and keep the exact-order expect_equal, that one holds in any locale
  • man/ wasn't re-documented, need to run devtools::document() and commit (usage/params are out of sync, R CMD check will complain)
  • factor_as_factor is inserted before na_level so positional calls like df_explicit_na(d, NULL, TRUE, FALSE, "MISS") now hit factor_as_factor instead of na_level and error. tern uses na_level by name everywhere so we're fine internally, but this is exported and used a lot in study code. can we move the 3 new args after na_level?

also please strip the auto-generated trailer from the PR description.

Comment thread R/df_explicit_na.R Outdated
Comment thread tests/testthat/test-df_explicit_na.R Outdated
- Move factor_as_factor/factor_level_method/factor_level_last_pattern
  after na_level to preserve positional call compatibility
- Update @param order in roxygen and man/df_explicit_na.Rd accordingly
- Replace match.arg() with checkmate::assert_choice() so error message
  matches test expectation and style is consistent with rest of file
- Drop expect_false(identical(...)) test line that fails under LC_COLLATE=C
  (testthat edition 3 forces C locale in CI)
@kaipingyang

Copy link
Copy Markdown
Contributor Author

I have read the CLA Document and I hereby sign the CLA

@kaipingyang

Copy link
Copy Markdown
Contributor Author

All four points addressed:

  • Moved factor_as_factor, factor_level_method, and factor_level_last_pattern after na_level to preserve positional call compatibility
  • Removed the expect_false(identical(...)) line that fails under LC_COLLATE=C
  • Re-ran devtools::document() and committed the updated man/df_explicit_na.Rd
  • Stripped the auto-generated trailer from the PR description

All 32 tests pass locally. Please re-review when you have a chance.

@shajoezhu

Copy link
Copy Markdown
Contributor

@copilot fix spell check

@shajoezhu shajoezhu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hi @kaipingyang , thanks for the changes. i made minor update, ci checks out, and downstream scda.test are all ok. thanks! Thanks @Melkiades for the review

@shajoezhu
shajoezhu dismissed Melkiades’s stale review July 12, 2026 23:23

changes were made. i made minor update, ci checks out, and downstream scda.test are all ok. thanks! Thanks @Melkiades for the review

@shajoezhu
shajoezhu merged commit ff79412 into insightsengineering:main Jul 13, 2026
57 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: <add factor_level_method argument for df_explicit_na function>

4 participants