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
Related
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))
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)}
Suppose I have this list:
my_variable <- list()
x <- c(1,2,3,4)
y <- c(4,5,7,3)
for ( i in 1:4){
my_variable[[i]] <- x[i]*y[i]+2
}
Then I will get this:
[[1]]
[1] 6
[[2]]
[1] 12
[[3]]
[1] 23
[[4]]
[1] 14
How to name the element of the output, like this:
> my_variable
First_result
[1] 6
Second_result
[1] 12
and so on.
You could do it with the paste0 and names
# So first you define vector of names:
names1 <- c("First","Second","Third","Fourth")
# And second you paste them to your list
names(my_variable) <- paste0(names1,"_result", sep = "")
#And the output
$First_result
[1] 6 12 23 14
$Second_result
[1] 6 12 23 14
$Third_result
[1] 6 12 23 14
$Fourth_result
[1] 6 12 23 14
Imagine, I have list of two levels:
lll <- list()
lll[[1]] <- list(1:10, 1:5, 1:2)
lll[[2]] <- list(10:20, 20:30)
lll
[[1]]
[[1]][[1]]
[1] 1 2 3 4 5 6 7 8 9 10
[[1]][[2]]
[1] 1 2 3 4 5
[[1]][[3]]
[1] 1 2
[[2]]
[[2]][[1]]
[1] 10 11 12 13 14 15 16 17 18 19 20
[[2]][[2]]
[1] 20 21 22 23 24 25 26 27 28 29 30
I want calculate means of these sequences. I have written a little function, which works fine:
func <- function(list.list){
lapply(1:length(list.list), function(i) mean(list.list[[i]]))
}
lapply(lll, func)
I don't like in this function, that I have to use anonymous function.
It gets even more complicated when I have list of 3 levels.
Maybe you know better ways to make calculations in which anonymous function would not be included? Should I use higher-order functions (Map, Reduce)?
I know how to write for cycle, but in this case it isn't an option.
Here's a possible solution (using rapply = recursive apply) working at any level of depth :
lll <- list()
lll[[1]] <- list(1:10, 1:5, 1:2)
lll[[2]] <- list(10:20, 20:30)
res <- rapply(lll,mean,how='replace')
> res
[[1]]
[[1]][[1]]
[1] 5.5
[[1]][[2]]
[1] 3
[[1]][[3]]
[1] 1.5
[[2]]
[[2]][[1]]
[1] 15
[[2]][[2]]
[1] 25
Setting argument how='unlist' you will get :
res <- rapply(lll,mean,how='replace')
> res
[1] 5.5 3.0 1.5 15.0 25.0
Say, I have the following recursive list:
rec_list <- list(list(rep(1,5), 10), list(rep(100, 4), 20:25))
rec_list
[[1]]
[[1]][[1]]
[1] 1 1 1 1 1
[[1]][[2]]
[1] 10
[[2]]
[[2]][[1]]
[1] 100 100 100 100
[[2]][[2]]
[1] 20 21 22 23 24 25
Now, I would like to replace all the values of the list, say, with the vector seq_along(unlist(rec_list)), and keep the structure of the list. I tried using the empty index subsetting like
rec_list[] <- seq_along(unlist(rec_list))
But this doesn't work.
How can I achieve the replacement while keeping the original structure of the list?
You can use relist:
relist(seq_along(unlist(rec_list)), skeleton = rec_list)
# [[1]]
# [[1]][[1]]
# [1] 1 2 3 4 5
#
# [[1]][[2]]
# [1] 6
#
#
# [[2]]
# [[2]][[1]]
# [1] 7 8 9 10
#
# [[2]][[2]]
# [1] 11 12 13 14 15 16
If you wanted to uniquely index each element of a nested list, you could start with the rapply() function which is the recursive form of the apply() family. Here I use a special function that can uniquely index across a list of any structure
rapply(rec_list,
local({i<-0; function(x) {i<<-i+length(x); i+seq_along(x)-length(x)}}),
how="replace")
other functions are simplier, for example if you just wanted to seq_along each subvector
rapply(rec_list, seq_along, how="replace")