I am using this code that generates 3 random numbers that add to 72:
# https://stackoverflow.com/questions/24845909/generate-n-random-integers-that-sum-to-m-in-r
rand_vect <- function(N, M, sd = 1, pos.only = TRUE) {
vec <- rnorm(N, M/N, sd)
if (abs(sum(vec)) < 0.01) vec <- vec + 1
vec <- round(vec / sum(vec) * M)
deviation <- M - sum(vec)
for (. in seq_len(abs(deviation))) {
vec[i] <- vec[i <- sample(N, 1)] + sign(deviation)
}
if (pos.only) while (any(vec < 0)) {
negs <- vec < 0
pos <- vec > 0
vec[negs][i] <- vec[negs][i <- sample(sum(negs), 1)] + 1
vec[pos][i] <- vec[pos ][i <- sample(sum(pos ), 1)] - 1
}
vec
}
If I run this code 100 times:
results <- list()
for (i in 1:100)
{
r_i = rand_vect(3,72)
results[[i]] <- r_i
}
When I look at the numbers that came out:
[[1]]
[1] 23 24 25
[[2]]
[1] 25 24 23
[[3]]
[1] 24 25 23
[[4]]
[1] 23 24 25
[[5]]
[1] 25 24 23
[[6]]
[1] 24 24 24
[[7]]
[1] 24 25 23
[[8]]
[1] 24 25 23
[[9]]
[1] 24 25 23
[[10]]
[1] 24 23 25
In each iteration, all the numbers add to 72 as expected - but the numbers don't really "look that random". They all seem to be "clumped" around "24, 23, 25". I was hoping to see more "randomness" in these numbers. For example:
[[11]]
[1] 5 50 17
[[12]]
[1] 12 40 20
Why are the numbers in the code I am using "clumped" around 24, 23, 25 - and how can I change the above code so that there is more "randomness" in the numbers being generated?
Thank you!
If you just want three random integers that sum to 72 you could do something like
diff(c(0, sort(sample(72, 2)), 72))
Related
I am stuck with a sum that I don't know how to solve this problem. I need to sum even numbers from 2 to 20, and this numbers sum 3.
n<-20
j<-0
for (i in 1:n) {
if(i %% 2 == 0)
j<-i+3
print(j)
}
Output:
[1] 0
[1] 5
[1] 5
[1] 7
[1] 7
[1] 9
[1] 9
[1] 11
[1] 11
[1] 13
[1] 13
[1] 15
[1] 15
[1] 17
[1] 17
[1] 19
[1] 19
[1] 21
[1] 21
[1] 23
With the function that I used I got the answer, but I don't know why it is repeated twice.
Add curly braces:
for (i in 1:n) {
if(i %% 2 == 0){
j <- i+3
print(j)
}
}
You can get the same outcome without using the loop:
vec <- 1:20
vec[vec %% 2 == 0] + 3
i will generate permutations of a partitions.
i generate partitions with this code:
library(partitions)
x <- c(2,4,6)
parts <- listParts(length(x))
out <- rapply(parts, function(ii) x[ii], how="replace")
and generate
out
[[1]]
[1] (2,4,6)
[[2]]
[1] (2,6)(4)
[[3]]
[1] (2,4)(6)
[[4]]
[1] (4,6)(2)
[[5]]
[1] (2)(4)(6)
take a element for example [1](2)(4)(6) i would generate all possible permutations. I tried with:
library(combinat)
permn(x)
but the return element is not in the same form of input,for example with element
[1](21,33,41,40,39,3,6)(13,37) return:
[[1]]
[[1]]$`1`
[1] 21 33 41 40 39 3 6
[[1]]$`2`
[1] 13 37
[[2]]
[[2]]$`2`
[1] 13 37
[[2]]$`1`
[1] 21 33 41 40 39 3 6
i do similar question some week ago, but the solution that was given to when generate partitions generate permutations for all possible partitions, but for problem of
efficiency i can't use it.
the solution this was it:
library(partitions)
permListParts <- function (x)
{
f <- function(pp) {
out <- split(seq_along(pp), pp)
myPerms <- perms(length(out))
apply(myPerms, 2, function(x) {
temp <- out[x]
class(temp) <- c(class(temp), "equivalence")
temp
})
}
apply(setparts(x), 2, f)}
Problem:
I have a list of two lists of three vectors. I would like to remove the zero vector from each sublist.
Example:
x <- list(x1=c(0,0,0), x2=c(3,4,5), x3=c(45,34,23))
y <- list(y1=c(2,33,4), y2=c(0,0,0), y3=c(4,5,44))
z <- list(x, y)
Try:
I tried this:
res <- lapply(1:2, function(i) {lapply(1:3, function(j) z[[i]][[j]][z[[i]][[j]] != 0])})
Which gave me this:
> res
[[1]]
[[1]][[1]]
numeric(0)
[[1]][[2]]
[1] 3 4 5
[[1]][[3]]
[1] 45 34 23
[[2]]
[[2]][[1]]
[1] 2 33 4
[[2]][[2]]
numeric(0)
[[2]][[3]]
[1] 4 5 44
Problem with the output:
I do not want numeric(0).
Expected output:
x= list(x2, x3)
y=list(y1, y3)
Any idea, please?
You can try a tidyverse if the nested list structure is not important
library(tidyverse)
z %>%
flatten() %>%
keep(~all(. != 0))
$x2
[1] 3 4 5
$x3
[1] 45 34 23
$y1
[1] 2 33 4
$y3
[1] 4 5 44
Given your structure of list of lists I would go with the following:
filteredList <- lapply(z, function(i) Filter(function(x) any(x != 0), i))
x <- filteredList[[1]]
y <- filteredList[[2]]
x
##$`x2`
##[1] 3 4 5
##$x3
##[1] 45 34 23
y
##$`y1`
##[1] 2 33 4
##$y3
##[1] 4 5 44
define z as
z <- c(x, y)
# z <- unlist(z, recursive = F) if you cannot define z by yourself.
then use:
z[sapply(z, any)]
#$`x2`
#[1] 3 4 5
#$x3
#[1] 45 34 23
#$y1
#[1] 2 33 4
#$y3
#[1] 4 5 44
Please note:
As in the tradition of lang C. Every integer/ numeric != 0 will be casted to TRUE. So in this task we can use this logic. ?any will eval FALSE if all values are 0.
Or:
x <- list(x1=c(0,0,0), x2=c(3,4,5), x3=c(45,34,23))
y <- list(y1=c(2,33,4), y2=c(0,0,0), y3=c(4,5,44))
z <- list(x, y)
lapply(z, function(a) a[unlist(lapply(a, function(b) !identical(b, rep(0,3))))])
#[[1]]
#[[1]]$`x2`
#[1] 3 4 5
#
#[[1]]$x3
#[1] 45 34 23
#
#
#[[2]]
#[[2]]$`y1`
#[1] 2 33 4
#
#[[2]]$y3
#[1] 4 5 44
with purrr it can be really compact
library(purrr)
map(z, keep ,~all(.!=0))
# [[1]]
# [[1]]$x2
# [1] 3 4 5
#
# [[1]]$x3
# [1] 45 34 23
#
#
# [[2]]
# [[2]]$y1
# [1] 2 33 4
#
# [[2]]$y3
# [1] 4 5 44
If it wasn't for the annoying warnings we could do just map(z, keep , all)
I have a question about sampling: I would like to sample successive number in a vector without replacement. Is there a simple way to do so?
For example,
sample(c(1:100), 10, replace = F)
76 99 94 53 12 34 5 82 75 30
gives me 10 number between 1 and 100. Now I would like to have 10 sequence of 3 successive integer without replacement: c(2,3,4), c(10,11,12), c(82,83,84) etc.
The different sequences can't overlap, that is if c(2,3,4) is my first sampling, then none of the following one can have these numbers.
I would even look for the possibility of sampling 10 sequences of different sizes, the sizes given by a vector like
sizevec <- sample(c(1:4),10,replace = T)
Thanks for the help
set.seed(42)
lapply(sample(1:10, 1) + cumsum(sample(4:10, 10, TRUE)), function(x) x + 1:3)
# [[1]]
# [1] 21 22 23
# [[2]]
# [1] 27 28 29
# [[3]]
# [1] 36 37 38
# [[4]]
# [1] 44 45 46
# [[5]]
# [1] 51 52 53
# [[6]]
# [1] 60 61 62
# [[7]]
# [1] 64 65 66
# [[8]]
# [1] 72 73 74
# [[9]]
# [1] 80 81 82
# [[10]]
# [1] 87 88 89
A solution using tow while loop to take samples. After running the code, x is a list of desired output.
# Set seed for reproduciblility
set.seed(123)
# Create a list to store values
x <- list()
# Create a vector to store values in x
y <- integer()
# Set the threshold to stop
threshold <- 4
# Set the condition
condition <- TRUE
while (length(x) < threshold){
while (condition){
# Sample a number between 1 to 98
s <- sample(c(1:98), 1)
# Create a sequence
se <- s:(s + 2)
# Check if the values in se is in y, save it to the condition
condition <- any(se %in% y)
}
# Save se to the list
x[[length(x) + 1]] <- se
# Update y
y <- unlist(x)
# Reset the condition
condition <- TRUE
}
# View the results
x
# [[1]]
# [1] 29 30 31
#
# [[2]]
# [1] 79 80 81
#
# [[3]]
# [1] 41 42 43
#
# [[4]]
# [1] 89 90 91
HI you are unclear if the vectors may overlap or not. assuming the may overlap this should work
lapply(sample(c(1:97), 10, replace = F),function(i){ 0:2 + i})
having a random length would then look like this
lapply(sample(c(1:97), 10, replace = F),function(i){ 0:sample(1:10,1) + i})
I want to create the following list
myList[[1]][1] 10
myList[[1]][2] 20
myList[[1]][3] 30 40
So I write the following code but it seems that I am doing it wrong:
myList <- vector(mode = "list")
myList[[length(myList)+1]] <- 10
# myList[[length(myList)+1]][1] <- 10 # it seems more reasonable, but it does not work either
myList[[length(myList)]][2] <- 20
myList[[length(myList)]][3] <- c(30, 40)
print(myList)
Should the third element myList[[1]][3] be a list too ?
You cannot create this list:
myList[[1]][1] 10
myList[[1]][2] 20
myList[[1]][3] 30 40
This would imply that myList[[1]] would be equal to:
[1] 10
[2] 20
[3] 30 40
Which is not an acceptable variable in R, since you are implying that element 3 of the vector is a vector itself.
However, this is:
[[1]]
[1] 10
[[2]]
[1] 20
[[3]]
[1] 30 40
So you can do:
myList = list()
myList = c(myList, 10)
myList = c(myList, 20)
myList = c(myList, list(c(30, 40)))
Which results in
> myList
[[1]]
[1] 10
[[2]]
[1] 20
[[3]]
[1] 30 40