Skip to content

Commit 358087c

Browse files
authored
Merge pull request #95 from jmbarbone/85-hot
Adds `hold()` and `toss()`
2 parents 64e20cd + 4d8d360 commit 358087c

14 files changed

Lines changed: 223 additions & 10 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: fuj
22
Type: Package
33
Title: Functions and Utilities for Jordan
4-
Version: 0.2.2.9005
4+
Version: 0.2.2.9006
55
Authors@R:
66
person(
77
given = "Jordan Mark",

NAMESPACE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export(exattr)
2929
export(file_path)
3030
export(flip)
3131
export(fp)
32+
export(hold)
3233
export(include)
3334
export(is_file_path)
3435
export(is_in)
@@ -64,6 +65,7 @@ export(subset1)
6465
export(subset2)
6566
export(subset3)
6667
export(subtract)
68+
export(toss)
6769
export(vap)
6870
export(vap2)
6971
export(vap2_chr)
@@ -91,6 +93,7 @@ export(vap_dttm)
9193
export(vap_int)
9294
export(vap_lgl)
9395
export(vap_raw)
96+
export(vap_vec)
9497
export(vapi)
9598
export(vapi_chr)
9699
export(vapi_cpl)

NEWS.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* `list0()`'s functionality to ignore empty inputs can be disabled if `options(fuj.list.active = FALSE)` before `{fuj}` is loaded [#91](https://github.com/jmbarbone/fuj/issues/91)
88
* `set_file_ext()` and `file_ext<-()` added for controlling file extensions [#89](https://github.com/jmbarbone/fuj/issues/89)
99
* `+` and `/` methods added for `file_path` classes, allowing path creation (e.g., `fp("folder") / "subfolder" / "file" + "extension"`) [#89](https://github.com/jmbarbone/fuj/issues/89)
10+
* `hold()` and `toss()` are added for retaining and removing values in a vectors [#85](https://github.com/jmbarbone/fuj/issues/85)
1011

1112
## Changes in `conditions`
1213

@@ -45,7 +46,9 @@ Arguments to `f())` can use any name.
4546

4647
_Note_: `vapi()` uses either the index or names of `x` as the second argument to `f`.
4748

48-
Each `vap` function comes with the following type variants:
49+
50+
Each `vap` function comes with the following type variants.
51+
If you are not concerned about type safety, use`vap_vec()`.
4952

5053
| Function | Output Type | Conversion
5154
|:-----------|----------------|----------------|

R/condition.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ new_condition <- function(
9393
}
9494

9595
type <- as.character(type)
96-
type <- match.arg(type)
96+
type <- match.arg(type, c("condition", "error", "warning", "message"))
9797

9898
if (!inherits(class, "AsIs")) {
9999
class <- vapply(

R/conditions.R

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ verbose_message <- function(message, call = NULL) {
2323

2424
# errors ------------------------------------------------------------------
2525

26-
input_error <- function(message = "invalid input") {
26+
input_error <- function(message = "invalid input", ...) {
2727
new_condition(
28-
message = message,
28+
message = c(message, ...),
2929
class = "input",
3030
type = "error",
3131
package = "fuj"
3232
)
3333
}
3434

35-
value_error <- function(message = "invalid value") {
35+
value_error <- function(message = "invalid value", ...) {
3636
new_condition(
37-
message = message,
37+
message = c(message, ...),
3838
class = "value",
3939
type = "error",
4040
package = "fuj"

R/flip.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ flip.matrix <- function(
4343
...
4444
) {
4545
switch(
46-
match.arg(by),
46+
match.arg(by, c("rows", "columns")),
4747
rows = {
4848
rows <- nrow(x)
4949
dims <- dimnames(x)
@@ -87,7 +87,7 @@ flip.data.frame <- function(
8787
...
8888
) {
8989
switch(
90-
match.arg(by),
90+
match.arg(by, c("rows", "columns")),
9191
rows = {
9292
rows <- nrow(x)
9393

R/hot.R

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#' Hold or Toss
2+
#'
3+
#' @param x A vector of values
4+
#' @param i An indication of which subset values to action. This can be a
5+
#' logical vector, an integer vector, or a function that takes `x` as an
6+
#' argument and returns a logical or integer vector
7+
#' @param na How to handle `NA` values in when `p` is a logical vector, or a
8+
#' function that returns a logical vector. [fuj::hold()] defaults to dropping
9+
#' `NA` values, while [fuj::toss()] defaults to keeping `NA` values. When `p`
10+
#' is an integer vector, `NA` values are always dropped.
11+
#' @name hot
12+
#' @examples
13+
#' x <- c(1, NA, 3, 4, Inf, 6)
14+
#' twos <- function(x) x %% 2 == 0
15+
#' hold(x, twos) # 4, 6
16+
#' toss(x, twos) # 1, 3, NA, Inf
17+
#'
18+
#' hold(x, twos, na = "keep") # NA, 4, Inf, 6
19+
#' toss(x, twos, na = "drop") # 1, 3
20+
#'
21+
#' i <- c(1:3, NA)
22+
#' x <- letters[1:5]
23+
#' hold(x, i)
24+
#' toss(x, i)
25+
#'
26+
#' @returns
27+
#' - [fuj::hold()] **retains** values in `x` matched against `i`
28+
#' - [fuj::toss()] **removes** values in `x` matched against `i`
29+
NULL
30+
31+
#' @rdname hot
32+
#' @export
33+
hold <- function(x, i, na = c("drop", "keep")) {
34+
na <- match.arg(na, c("drop", "keep"))
35+
36+
if (inherits(i, "logical")) {
37+
i[is.na(i)] <- na == "keep"
38+
return(x[i])
39+
}
40+
41+
if (integerish(i)) {
42+
return(x[i[!is.na(i)]])
43+
}
44+
45+
if (is.function(i)) {
46+
return(hold(x, vap_vec(x, i), na = na))
47+
}
48+
49+
stop(hot_input_error())
50+
}
51+
52+
53+
#' @rdname hot
54+
#' @export
55+
toss <- function(x, i, na = c("keep", "drop")) {
56+
na <- match.arg(na, c("keep", "drop"))
57+
58+
if (is.logical(i)) {
59+
i[is.na(i)] <- na == "drop"
60+
return(x[!i])
61+
}
62+
63+
if (integerish(i)) {
64+
return(x[-i[!is.na(i)]])
65+
}
66+
67+
if (is.function(i)) {
68+
return(toss(x, vap_vec(x, i), na = na))
69+
}
70+
71+
stop(hot_input_error())
72+
}
73+
74+
hot_input_error <- function() {
75+
input_error(
76+
"i must be logical, integer, integer-like numeric, or function which",
77+
" returns a logical, integer, or integer-like numeric"
78+
)
79+
}

R/muffle.R

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ do_muffle <- function(
4242
classes,
4343
env = parent.frame()
4444
) {
45-
type <- match.arg(type)
45+
type <- match.arg(type, c("muffle", "wuffle"))
4646

4747
if (missing(fun)) {
4848
fun <- switch(type, muffle = suppressMessages, wuffle = suppressWarnings)

R/utils.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ pairlist_to_string <- function(pair) {
99
vals <- as.character(pair)
1010
paste(nms, "=", vals, collapse = ", ")
1111
}
12+
13+
integerish <- function(x) {
14+
is.integer(x) ||
15+
(is.numeric(x) &&
16+
!any(is.infinite(x)) &&
17+
all(x == as.integer(x), na.rm = TRUE))
18+
}

R/vap.R

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ vap_dates_ <- function(fun, type) {
148148
#' in unexpected outputs. Likely, warnings or errors will be signaled
149149
#' accordingly.
150150
#'
151+
#' [vap_vec()] is a variant of [vap()] that returns a _flattened_ vector. This
152+
#' has similar behavior as [base::sapply()], in that a `list` will be returned
153+
#' if the [base::unlist()]'d output has multiple values in an element.
154+
#'
151155
#' [with_vap_progress()] sets an option `vap.progress` to `TRUE` for the
152156
#' duration of `expr`, which causes a progress bar to be displayed for any
153157
#' `vap*` calls inside `expr`.
@@ -242,6 +246,20 @@ vapp <- function(p, f, ...) {
242246
set_vapp_names(out, p[[1L]])
243247
}
244248

249+
#' @export
250+
#' @rdname vap
251+
# nolint next: object_usage_linter.
252+
vap_vec <- function(x, f, ...) {
253+
delayedAssign("..call", sys.call())
254+
x <- vap(x, f, ...)
255+
y <- unlist(x, recursive = FALSE, use.names = FALSE)
256+
if (length(x) == length(y)) {
257+
set_vap_names(y, x)
258+
} else {
259+
x
260+
}
261+
}
262+
245263
# vap ---------------------------------------------------------------------
246264

247265
#' @export

0 commit comments

Comments
 (0)