Skip to content

Commit 6b8702e

Browse files
feat: Implement <expr>$item() (#1652)
1 parent 2ea1744 commit 6b8702e

File tree

15 files changed

+202
-46
lines changed

15 files changed

+202
-46
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ VignetteBuilder:
5353
Config/Needs/dev: devtools, lifecycle, readr, glue, RcppTOML, smvr
5454
Config/Needs/lint: fs, lintr
5555
Config/Needs/website: etiennebacher/altdoc, future.apply
56-
Config/polars/lib-version: 1.6.0-rc.1
56+
Config/polars/lib-version: 1.7.0-rc.1
5757
Config/testthat/edition: 3
5858
Config/testthat/parallel: true
5959
Config/testthat/start-first: lazyframe-frame, *-s3-base, polars_options,

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## polars (development version)
44

5+
### New features
6+
7+
- `<expr>$item()` to strictly extract a single value from an expression (#1652).
8+
59
## polars 1.6.0
610

711
This is an update that corresponds to Python Polars 1.35.2.

R/000-wrappers.R

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,12 @@ class(`PlRDataTypeExpr`) <- c("PlRDataTypeExpr__bundle", "savvy_polars__sealed")
21362136
}
21372137
}
21382138

2139+
`PlRExpr_item` <- function(self) {
2140+
function(`allow_empty`) {
2141+
.savvy_wrap_PlRExpr(.Call(savvy_PlRExpr_item__impl, `self`, `allow_empty`))
2142+
}
2143+
}
2144+
21392145
`PlRExpr_kurtosis` <- function(self) {
21402146
function(`fisher`, `bias`) {
21412147
.savvy_wrap_PlRExpr(.Call(savvy_PlRExpr_kurtosis__impl, `self`, `fisher`, `bias`))
@@ -3586,6 +3592,7 @@ class(`PlRDataTypeExpr`) <- c("PlRDataTypeExpr__bundle", "savvy_polars__sealed")
35863592
e$`is_not_null` <- `PlRExpr_is_not_null`(ptr)
35873593
e$`is_null` <- `PlRExpr_is_null`(ptr)
35883594
e$`is_unique` <- `PlRExpr_is_unique`(ptr)
3595+
e$`item` <- `PlRExpr_item`(ptr)
35893596
e$`kurtosis` <- `PlRExpr_kurtosis`(ptr)
35903597
e$`last` <- `PlRExpr_last`(ptr)
35913598
e$`len` <- `PlRExpr_len`(ptr)

R/expr-expr.R

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4787,3 +4787,38 @@ expr__is_close <- function(other, ..., abs_tol = 0, rel_tol = 1e-09, nans_equal
47874787
self$`_rexpr`$is_close(as_polars_expr(other)$`_rexpr`, abs_tol, rel_tol, nans_equal)
47884788
})
47894789
}
4790+
4791+
#' Get the single value
4792+
#'
4793+
#' This raises an error if there is not exactly one value.
4794+
#'
4795+
#' @inheritParams rlang::args_dots_empty
4796+
#' @param allow_empty Allow having no values to return `null`.
4797+
#'
4798+
#' @seealso [$get()][expr__get] to get a single value by index.
4799+
#' @inherit as_polars_expr return
4800+
#' @examples
4801+
#' # This function may be useful to force ourselves to handle cases where we
4802+
#' # expect a single value but there are several. For example, we might expect
4803+
#' # `$mode()` to return a single value...
4804+
#' df <- pl$DataFrame(x = c("a", "a", "c"))
4805+
#' df$select(
4806+
#' mode = pl$col("x")$mode()$item()
4807+
#' )
4808+
#'
4809+
#' # ... but this is not always the case:
4810+
#' df <- pl$DataFrame(x = c("a", "b", "c"))
4811+
#' tryCatch(
4812+
#' {
4813+
#' df$select(
4814+
#' mode = pl$col("x")$mode()$item()
4815+
#' )
4816+
#' },
4817+
#' error = function(e) print(e)
4818+
#' )
4819+
expr__item <- function(..., allow_empty = FALSE) {
4820+
wrap({
4821+
check_dots_empty0(...)
4822+
self$`_rexpr`$item(allow_empty)
4823+
})
4824+
}

altdoc/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ nav:
331331
- is_not_null: man/expr__is_not_null.md
332332
- is_null: man/expr__is_null.md
333333
- is_unique: man/expr__is_unique.md
334+
- item: man/expr__item.md
334335
- kurtosis: man/expr__kurtosis.md
335336
- last: man/expr__last.md
336337
- le: man/expr__le.md

man/expr__item.Rd

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/init.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1579,6 +1579,11 @@ SEXP savvy_PlRExpr_is_unique__impl(SEXP self__) {
15791579
return handle_result(res);
15801580
}
15811581

1582+
SEXP savvy_PlRExpr_item__impl(SEXP self__, SEXP c_arg__allow_empty) {
1583+
SEXP res = savvy_PlRExpr_item__ffi(self__, c_arg__allow_empty);
1584+
return handle_result(res);
1585+
}
1586+
15821587
SEXP savvy_PlRExpr_kurtosis__impl(SEXP self__, SEXP c_arg__fisher, SEXP c_arg__bias) {
15831588
SEXP res = savvy_PlRExpr_kurtosis__ffi(self__, c_arg__fisher, c_arg__bias);
15841589
return handle_result(res);
@@ -3695,6 +3700,7 @@ static const R_CallMethodDef CallEntries[] = {
36953700
{"savvy_PlRExpr_is_not_null__impl", (DL_FUNC) &savvy_PlRExpr_is_not_null__impl, 1},
36963701
{"savvy_PlRExpr_is_null__impl", (DL_FUNC) &savvy_PlRExpr_is_null__impl, 1},
36973702
{"savvy_PlRExpr_is_unique__impl", (DL_FUNC) &savvy_PlRExpr_is_unique__impl, 1},
3703+
{"savvy_PlRExpr_item__impl", (DL_FUNC) &savvy_PlRExpr_item__impl, 2},
36983704
{"savvy_PlRExpr_kurtosis__impl", (DL_FUNC) &savvy_PlRExpr_kurtosis__impl, 3},
36993705
{"savvy_PlRExpr_last__impl", (DL_FUNC) &savvy_PlRExpr_last__impl, 1},
37003706
{"savvy_PlRExpr_len__impl", (DL_FUNC) &savvy_PlRExpr_len__impl, 1},

src/rust/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/rust/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "r-polars"
3-
version = "1.6.0-rc.1"
3+
version = "1.7.0-rc.1"
44
edition = "2024"
55
rust-version = "1.89.0"
66
publish = false

src/rust/api.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ SEXP savvy_PlRExpr_is_not_nan__ffi(SEXP self__);
321321
SEXP savvy_PlRExpr_is_not_null__ffi(SEXP self__);
322322
SEXP savvy_PlRExpr_is_null__ffi(SEXP self__);
323323
SEXP savvy_PlRExpr_is_unique__ffi(SEXP self__);
324+
SEXP savvy_PlRExpr_item__ffi(SEXP self__, SEXP c_arg__allow_empty);
324325
SEXP savvy_PlRExpr_kurtosis__ffi(SEXP self__, SEXP c_arg__fisher, SEXP c_arg__bias);
325326
SEXP savvy_PlRExpr_last__ffi(SEXP self__);
326327
SEXP savvy_PlRExpr_len__ffi(SEXP self__);

0 commit comments

Comments
 (0)