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
Plotting Average of Multiple Variables in Time-Series Using Ggplot
Shiny: Switching Between Reactive Data Sets with Rhandsontable
Find *All* Duplicated Records in Data.Table (Not All-But-One)
Get Stack Trace on Trycatch'Ed Error in R
Convert a Vector into a List, Each Element in the Vector as an Element in the List
Shiny + Ggplot: How to Subset Reactive Data Object
Multiply Columns in a Data Frame by a Vector
Ggplot: Manual Color Assignment for Single Variable Only
Extracting Coefficients and Their Standard Error for Each Unit in an Lme Model Fit
Retrieve Census Tract from Coordinates
Combine Voronoi Polygons and Maps
How to Manipulate Null Elements in a Nested List
How to Create a List in R from Two Vectors (One Would Be the Keys, the Other the Values)
Scraping from Aspx Website Using R
Importing Wikipedia Tables in R
Beginner Tips on Using Plyr to Calculate Year-Over-Year Change Across Groups