Reputation: 6409
I have a vector with varying length, which can sometimes be of length 1.
I would like to sample from this vector such that if its length is 1 it always samples that 1 number.
sample()
won't do this because it samples from 1 to the digit when sample size is 1.
Upvotes: 29
Views: 5409
Reputation: 46
You can use resample()
from the gdata package. This saves you having to redefine resample in each new script. As calling library(gdata)
masks a few functions and comes up with a few messages, you may consider using the double colon notation to call with gdata::resample()
.
https://www.rdocumentation.org/packages/gdata/versions/2.18.0/topics/resample
Upvotes: 0
Reputation: 6679
You could use this 'bugfree' redefinition of the function:
sample = function(x, size, replace = F, prob = NULL) {
if (length(x) == 1) return(x)
base::sample(x, size = size, replace = replace, prob = prob)
}
Test it:
> sapply(1:7, base::sample, size = 1)
[1] 1 2 2 4 4 4 4
> sapply(1:7, sample)
[1] 1 2 3 4 5 6 7
Upvotes: 1
Reputation: 108593
When fed only one single number, sample
works like sample.int
(see ?sample
). If you want to make sure it only samples from the vector you give it, you can work with indices and use this construct:
x[sample(length(x))]
This gives you the correct result regardless the length of x
, and without having to add an if
-condition checking the length.
Example:
mylist <- list(
a = 5,
b = c(2,4),
d = integer(0)
)
mysample <- lapply(mylist,function(x) x[sample(length(x))])
> mysample
$a
[1] 5
$b
[1] 2 4
$d
integer(0)
Note : you can replace sample
by sample.int
to get a little speed gain.
Upvotes: 22
Reputation: 89097
This is a documented feature:
If
x
has length1
, isnumeric
(in the sense ofis.numeric
) andx >= 1
, sampling via sample takes place from1:x
. Note that this convenience feature may lead to undesired behaviour whenx
is of varying length in calls such assample(x)
.
An alternative is to write your own function to avoid the feature:
sample.vec <- function(x, ...) x[sample(length(x), ...)]
sample.vec(10)
# [1] 10
sample.vec(10, 3, replace = TRUE)
# [1] 10 10 10
Some functions with similar behavior are listed under seq vs seq_along. When will using seq cause unintended results?
Upvotes: 31