This provides a common interface to extracting and modifying observations
for all vector types, regardless of dimensionality. It is an analog to [
that matches vec_size()
instead of length()
.
Usage
vec_slice(x, i, ..., error_call = current_env())
vec_slice(x, i) <- value
vec_assign(x, i, value, ..., x_arg = "", value_arg = "")
Arguments
- x
A vector
- i
An integer, character or logical vector specifying the locations or names of the observations to get/set. Specify
TRUE
to index all elements (as inx[]
), orNULL
,FALSE
orinteger()
to index none (as inx[NULL]
).- ...
These dots are for future extensions and must be empty.
- error_call
The execution environment of a currently running function, e.g.
caller_env()
. The function will be mentioned in error messages as the source of the error. See thecall
argument ofabort()
for more information.- value
Replacement values.
value
is cast to the type ofx
, but only if they have a common type. See below for examples of this rule.- x_arg, value_arg
Argument names for
x
andvalue
. These are used in error messages to inform the user about the locations of incompatible types and sizes (seestop_incompatible_type()
andstop_incompatible_size()
).
Genericity
Support for S3 objects depends on whether the object implements a
vec_proxy()
method.
When a
vec_proxy()
method exists, the proxy is sliced andvec_restore()
is called on the result.Otherwise
vec_slice()
falls back to the base generic[
.
Note that S3 lists are treated as scalars by default, and will
cause an error if they don't implement a vec_proxy()
method.
Differences with base R subsetting
vec_slice()
only slices along one dimension. For two-dimensional types, the first dimension is subsetted.vec_slice()
preserves attributes by default.vec_slice<-()
is type-stable and always returns the same type as the LHS.
Dependencies
base dependencies
If a non-data-frame vector class doesn't have a vec_proxy()
method, the vector is sliced with [
instead.
Examples
x <- sample(10)
x
#> [1] 6 5 7 1 2 4 3 10 9 8
vec_slice(x, 1:3)
#> [1] 6 5 7
# You can assign with the infix variant:
vec_slice(x, 2) <- 100
x
#> [1] 6 100 7 1 2 4 3 10 9 8
# Or with the regular variant that doesn't modify the original input:
y <- vec_assign(x, 3, 500)
y
#> [1] 6 100 500 1 2 4 3 10 9 8
x
#> [1] 6 100 7 1 2 4 3 10 9 8
# Slicing objects of higher dimension:
vec_slice(mtcars, 1:3)
#> mpg cyl disp hp drat wt qsec vs am gear carb
#> Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#> Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#> Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
# Type stability --------------------------------------------------
# The assign variant is type stable. It always returns the same
# type as the input.
x <- 1:5
vec_slice(x, 2) <- 20.0
# `x` is still an integer vector because the RHS was cast to the
# type of the LHS:
vec_ptype(x)
#> integer(0)
# Compare to `[<-`:
x[2] <- 20.0
vec_ptype(x)
#> numeric(0)
# Note that the types must be coercible for the cast to happen.
# For instance, you can cast a double vector of whole numbers to an
# integer vector:
vec_cast(1, integer())
#> [1] 1
# But not fractional doubles:
try(vec_cast(1.5, integer()))
#> Error in eval(expr, envir, enclos) :
#> Can't convert from `1.5` <double> to <integer> due to loss of precision.
#> • Locations: 1
# For this reason you can't assign fractional values in an integer
# vector:
x <- 1:3
try(vec_slice(x, 2) <- 1.5)
#> Error in `vec_slice<-`(`*tmp*`, 2, value = 1.5) :
#> Can't convert from `1.5` <double> to <integer> due to loss of precision.
#> • Locations: 1