Commit ff79412
feat: add factor_level_method, factor_as_factor, factor_level_last_pattern to df_explicit_na (#1487)
## 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
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Joe Zhu <joe.zhu@roche.com>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>1 parent 1303be4 commit ff79412
6 files changed
Lines changed: 181 additions & 4 deletions
File tree
- R
- inst
- man
- tests/testthat
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
4 | 12 | | |
5 | 13 | | |
6 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
24 | 46 | | |
25 | 47 | | |
26 | 48 | | |
| |||
66 | 88 | | |
67 | 89 | | |
68 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
69 | 101 | | |
70 | 102 | | |
71 | 103 | | |
72 | 104 | | |
73 | 105 | | |
74 | | - | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
75 | 110 | | |
76 | 111 | | |
77 | 112 | | |
78 | 113 | | |
| 114 | + | |
79 | 115 | | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
80 | 119 | | |
81 | 120 | | |
82 | 121 | | |
| |||
99 | 138 | | |
100 | 139 | | |
101 | 140 | | |
| 141 | + | |
102 | 142 | | |
103 | 143 | | |
104 | 144 | | |
| |||
112 | 152 | | |
113 | 153 | | |
114 | 154 | | |
115 | | - | |
116 | | - | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
117 | 172 | | |
118 | 173 | | |
119 | 174 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
| 41 | + | |
| 42 | + | |
40 | 43 | | |
41 | 44 | | |
42 | 45 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
0 commit comments