Select Random Element in a List of R

Select random element in a list of R?

# Sample from the vector 'a' 1 element.
sample(a, 1)

R: Randomly Selecting Items from a List

It seems straight-forward unless I am missing something, you have a list of foods and days, so just keep track of the available options each time you run through a person and only select from those options:

## initialize the inputs
set.seed(1)
foods <- letters[1:20]
nfoods <- sample(5, 4)
tmp <- list(unpicked = list(food = foods, days = 1:365))

## run it
tmp <- lapply(nfoods, function(x) tmp <<- f(tmp$unpicked$food, x, tmp$unpicked$days))

## summarize it
res <- sapply(seq_along(tmp), function(ii) {
x <- tmp[[ii]]
x <- sprintf('person %s: "%s" and "%s"', ii, toString(x$picked$food),
paste0(x$picked$days, collapse = '-'))
cat(x, sep = '\n')
invisible(x)
})
# person 1: "b" and "270-299"
# person 2: "s, a, k, g" and "306-336"
# person 3: "m, t, h" and "42-89"
# person 4: "j, f, q, o, l" and "129-210"

f <- function(food, n, days) {
# f(1:4, 3, 1:10)
food1 <- sample(food, n)

days1 <- split(days, cumsum(is.na(days)))
days1 <- sample(Filter(function(x) length(x) > 2, days1), 1)[[1]]
days1 <- sort(sample(sort(days1), 2))

days[do.call('seq', as.list(days1))] <- NA

list(
picked = list(food = food1, days = days1),
unpicked = list(food = setdiff(food, food1), days = days)
)
}

Select random elements from the list

This should work:

allFiles <- list.files("D:/test")

for( i in seq_along(allFiles) )
{
randomFiles <- sample(allFiles[-i], size = 10)
#...
}

Or you could also use one of those very useful set functions:

for( f in allFiles )
{
randomFiles <- sample(setdiff(allFiles, f), size = 10)

#...
}

Randomly extract elements in a list which belongs to a list and know the postition

Thanks to @akrun reminding me melt() function. Here is the solution to my question:

example_list <- list(matrix(c(1,2,3,4)),matrix(c(1,0,0,0,1)),matrix(1:12,3,4),matrix(1:12,4,3))
# To avoid getting NA, I transform arrays in list to matrix, so that I can get the index of rows and columns.
get_res <- function(example_list){
output <- melt(setNames(example_list,seq_along(rates)))
res <- output[sample(dim(output)[1], 1),] # sample(dim(output)[1], 1) This confirms I get only one number
if (as.integer(res$L1) <= 2){
ind1 = res$L1
ind2 = res$Var1}
else{ind1 = res$L1
ind2 = c(res$Var1,res$Var2)}
result <- list(ind1 = ind1, ind2 = ind2)
return(result)}
get_res(example_list)

in1 tells the sub list the random belongs to, and ind2 tell the order of the random in this sub list.

Randomly select a sample in R

sample will be the easiest way. As I understand, you want to get name of the set?

If so, then use

sample(c('s1', 's2', 's3', 's4', 's5', 's6'), size = 1, prob = c(20, 10, 10, 25, 15, 20))

In case you want to get a set itself use list of sets as an object to draw from (you need to add [[1]] at the end of the statement):

sample(list(s1, s2, s3, s4, s5, s6), size = 1, prob = c(20, 10, 10, 25, 15, 20))[[1]]

How to select a random vector

This is easier to do if you store your vectors in a list:

vecs <- list(
A = c(4, 4, 4, 4, 0, 0),
B = c(3, 3, 3, 3, 3, 3),
C = c(6, 6, 2, 2, 2, 2),
D = c(5, 5, 5, 1, 1, 1)
)

idx <- sample(1:length(vecs), 2, replace = F)

sampled <- vecs[idx]

sampled

$D
[1] 5 5 5 1 1 1

$B
[1] 3 3 3 3 3 3

You can then access your two sampled vectors, regardless of their names, with sampled[[1]] and sampled[[2]].

Pick one random element from a vector for each row of a data.table

We can use group by option and then do sample

dt[, NextItem := sample(x, 1), by = Name]

Or you can also do this with .N instead of by

dt[, NextItem := sample(x, .N, replace = TRUE)]

Select random and unique elements from a vector

Using base R ave we could do something like

unique(ave(seq_along(a), a, FUN = function(x) if(length(x) > 1) head(sample(x), 1) else x))
#[1] 3 5 6

unique(ave(seq_along(a), a, FUN = function(x) if(length(x) > 1) head(sample(x), 1) else x))
#[1] 3 4 7

This generates an index for every value of a, grouped by a and then selects one random index value in each group.


Using same logic with sapply and split

sapply(split(seq_along(a), a), function(x) if(length(x) > 1) head(sample(x), 1) else x)

And it would also work with tapply

tapply(seq_along(a), a, function(x) if(length(x) > 1) head(sample(x), 1) else x)

The reason why we need to check the length (if(length(x) > 1)) is because from ?sample

If x has length 1, is numeric (in the sense of is.numeric) and x >= 1, sampling via sample takes place from 1:x.

Hence, when there is only one number (n) in sample(), it takes sample from 1:n (and not n) so we need to check it's length.

sample 1 element from each list in nested list in R to create groups of samples

You could use sapply to select 1 element from each list and use replicate to repeat it 10 times.

t(replicate(10, sapply(xxx_, sample, 1)))

# [,1] [,2] [,3] [,4]
# [1,] 15 7 9 10
# [2,] 15 8 9 3
# [3,] 13 14 4 19
# [4,] 5 14 12 10
# [5,] 13 20 9 3
# [6,] 5 18 12 16
# [7,] 5 1 11 2
# [8,] 6 14 11 19
# [9,] 5 8 12 3
#[10,] 5 17 4 2


Related Topics



Leave a reply



Submit