I would like to flatten this list of arguments
args <- list(
a = 1,
b = "2",
list = list(c = 3, d = list(d1 = 5, d2 = 6)),
e = data.frame(e1 = c("a", "b"), e2 = c(7, 8))
)
on this
args <- list(
a = 1,
b = "2",
c = 3,
d = list(d1 = 5, d2 = 6),
e = data.frame(e1 = c("a", "b"), e2 = c(7, 8))
)
Because I need get work this function call
g <- function(x, y, ...){
do.call(f, x, y, ...)
}
g(x = x1, y = y1, args)
That does not work:
reduce(
.x = args,
.f = function(x) {
ifelse(
is.list(x),
lapply(x, `[[`),
x
)
}
)
that throws
Error in fn(out, elt, ...) : unused argument (elt)
Update: to OPs new data:
purrr::c(flatten(args[1:3]), args[4])
$a
[1] 1
$b
[1] "2"
$c
[1] 3
$d
$d$d1
[1] 5
$d$d2
[1] 6
$e
e1 e2
1 a 7
2 b 8
As you already state in your question "I would like to flatten this list of arguments" -> We could use purrrs flatten() function:
library(purrr)
flatten(args)
$a
[1] 1
$b
[1] "2"
$c
[1] 3
$d
$d$d1
[1] 5
$d$d2
[1] 6
$e
[1] 5
You can try the code below using for loops
res <- c()
for (v in args) {
if (is.list(v) & !is.data.frame(v)) {
res <- c(res,v)
} else {
res <- c(res, list(v))
}
}
or via Reduce
res <- Reduce(
function(x,y) {
c(x, ifelse(is.list(y) & !is.data.frame(y), I, list)(y))
},
args,
c()
)
and you will obtain
> res
[[1]]
[1] 1
[[2]]
[1] "2"
$c
[1] 3
$d
$d$d1
[1] 5
$d$d2
[1] 6
[[5]]
e1 e2
1 a 7
2 b 8
The output of map always be the same dim. So you need a for loop.
output <- NULL
for (x in seq(length(args))) {
list <- args[x]
if (is.list(args[[x]]) && !is.data.frame(args[[x]])) {
list <- flatten(args[x])
}
output <- append(output, list)
}
output
$a
[1] 1
$b
[1] "2"
$c
[1] 3
$d
$d$d1
[1] 5
$d$d2
[1] 6
$e
e1 e2
1 a 7
2 b 8
Related
Given I have the vector and a target number
target.mountain <- 10
Roll_dice <- sample(1:6, 4, replace=TRUE)
With Roll_dice producing
[1] 6, 5, 3, 2 as an example
How can I produce a list of all numbers in Roll_dice with all the ways of adding them together by combining either 2, 3 or 4 of the values in Roll_dice together in a list
For example [1] 2, 3, 5, 5, 6, 7, 11, ....
I would like you to check out the RccpAlgos-package, which has some awesome (and fast!) functions for fast operations on combinations/permutations with constraints.
update
library(RcppAlgos)
library(vecsets)
library(data.table)
target.mountain <- 10
Roll_dice <- c(5, 5, 3, 2)
L <- lapply( 2:4, function(x) {
as.data.table(comboGeneral( Roll_dice,
x,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = target.mountain ),
keep.rownames = TRUE )
})
# [[1]]
# V1 V2
# 1: 5 5
#
# [[2]]
# V1 V2 V3
# 1: 2 3 5
#so 5-5 of 2-3-5 can be chosen to get to 10
#remaining dice
DT <- data.table::rbindlist( L, fill = TRUE )
remains <- lapply( transpose(DT), function(x) {
v <- as.vector(x)
v <- v[ !is.na(v) ]
sum( vecsets::vsetdiff( Roll_dice, v) )
})
remains
#witrh leftovers:
# $V1
# [1] 5
#
# $V2
# [1] 5
old answer
library(RcppAlgos)
target.mountain <- 10
Roll_dice <- c(6, 4, 5, 5)
sapply( 2:4, function(x) {
comboGeneral( Roll_dice,
x,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = target.mountain )
})
# [[1]]
# [,1] [,2]
# [1,] 4 6
# [2,] 5 5
#
# [[2]]
# [,1] [,2] [,3]
#
# [[3]]
# [,1] [,2] [,3] [,4]
Something like this?
> sapply(
+ 2:4,
+ function(k) combn(Roll_dice, k, sum)
+ )
[[1]]
[1] 11 9 8 8 7 5
[[2]]
[1] 14 13 11 10
[[3]]
[1] 16
Or do you need this?
> lapply(
+ setNames(2:4, 2:4),
+ function(k) target.mountain %in% combn(Roll_dice, k, sum)
+ )
$`2`
[1] FALSE
$`3`
[1] TRUE
$`4`
[1] FALSE
I am new in R and I have a task to create list of lists.
I tried this:
newl <- list()
newl <- append(newl, list(a = 1, b = "x"))
newl <- append(newl, list(a = 15, b = "y"))
newl <- append(newl, list(a = 10, b = "z"))
But append works like extend Python function:
$a
[1] 1
$b
[1] "x"
$a
[1] 15
$b
[1] "y"
$a
[1] 10
$b
[1] "z"
I want to get something like this:
[[1]]
$a
[1] 1
$b
[1] "x"
[[2]]
$a
[1] 15
$b
[1] "y"
[[3]]
$a
[1] 10
$b
[1] "z"
Also I want to have an opportunity to sort elements of my list of lists by parameter (for example, by a). It would look like this:
[[1]]
$a
[1] 1
$b
[1] "x"
[[2]]
$a
[1] 10
$b
[1] "z"
[[3]]
$a
[1] 15
$b
[1] "y"
Also it's important for me to have elements different types inside lists (int and string in the example). In real task it would be function, vector, double and matrix.
Maybe I need to choose another data type to solve my problem?
Actually you are already close to your desired output, but you may need another list() within append, e.g.,
newl <- list()
newl <- append(newl, list(list(a = 1, b = "x")))
newl <- append(newl, list(list(a = 15, b = "y")))
newl <- append(newl, list(list(a = 10, b = "z")))
such that
> newl
[[1]]
[[1]]$a
[1] 1
[[1]]$b
[1] "x"
[[2]]
[[2]]$a
[1] 15
[[2]]$b
[1] "y"
[[3]]
[[3]]$a
[1] 10
[[3]]$b
[1] "z"
If you want to sort by $a, you can try
> newl[order(sapply(newl, `[[`, "a"))]
[[1]]
[[1]]$a
[1] 1
[[1]]$b
[1] "x"
[[2]]
[[2]]$a
[1] 10
[[2]]$b
[1] "z"
[[3]]
[[3]]$a
[1] 15
[[3]]$b
[1] "y"
We could do a split
lst1 <- unname(split(newl, as.integer(gl(length(newl), 2, length(newl)))))
I am a beginner in R. I have a vast data set and I am trying to create a loop to optimize the time.
I have something like:
a <- c ('exam12', 'example22', 'e33')
b <- list (c (2,4,5,6), c (10,4,8,6), c (25, 3, 7, 30))
And I would like to use the strings of a as the name of objects for other values, obtaining, in my environment, something like:
exam <- c (2,4,5,6)
example <- c (10,4,8,6)
e <- c (25, 3, 7, 30)
I tried the following:
for (i in seq_along (a)) {
for (j in seq_along (b)) {
str_sub (a [i], start = 1, end = -1) <- b [j]
}
}
But I was not successful. I appreciate any help.
You can use list2env:
a <- c ('exam12', 'example22', 'e33')
b <- list (c (2,4,5,6), c (10,4,8,6), c (25, 3, 7, 30))
a
# [1] "exam12" "example22" "e33"
b
# [[1]]
# [1] 2 4 5 6
#
# [[2]]
# [1] 10 4 8 6
#
# [[3]]
# [1] 25 3 7 30
ls()
# [1] "a" "b"
list2env(setNames(b, sub("\\d+$", "", a)), .GlobalEnv)
# <environment: R_GlobalEnv>
ls()
# [1] "a" "b" "e" "exam" "example"
exam
# [1] 2 4 5 6
For reference, you could also do this with assign, for example:
for (i in seq_along(a)) {
assign(sub("\\d+$", "", a[i]), b[[i]])
}
I would like to add list elements iteratively in R, so that later elements can use the elements created earlier. The desired behavior is as follows:
lst <- list(a = 1,
b = 2,
c = b)
lst
## $a
## [1] 1
##
## $b
## [1] 2
##
## $c
## [1] 2
I know that I can easily accomplish the same using e.g.
lst <- list(a = 1,
b = 2)
lst[['c']] <- lst[['b']]
But I was wondering, if I could do this in one step.
Here's another way
rev(within(list(), { a = 1; b = 2; c = b }))
# $a
# [1] 1
#
# $b
# [1] 2
#
# $c
# [1] 2
Update: This is now possible with the lst function of the tibble package:
tibble::lst(a = 1, b = 2, c = b)
## $a
## [1] 1
##
## $b
## [1] 2
##
## $c
## [1] 2
My previous workaround was using mutate from plyr:
mylist <- function(...) plyr::mutate(.data=list(), ...)
mylist(a = 1,
b = 2,
c = b)
## $a
## [1] 1
##
## $b
## [1] 2
##
## $c
## [1] 2
A more classic idea:
mylist = function(...)
{
args = as.list(substitute(list(...)))[-1]
lapply(args, eval, envir = args)
}
mylist(a = 1, b = 2, c = a + b)
#$a
#[1] 1
#
#$b
#[1] 2
#
#$c
#[1] 3
For a strict iterative approach, a loop is needed:
mylist = function(...)
{
args = as.list(substitute(list(...)))[-1]
for(i in seq_along(args)) args[[i]] = eval(args[[i]], envir = args)
return(args)
}
mylist(a = 1, b = a + 1, c = b + 1)
#$a
#[1] 1
#
#$b
#[1] 2
#
#$c
#[1] 3
Been stuck with this for a while!
How can I manipulate the first list into the second?
list("X" = X, "Y" = Y, ...)
list("X" = c(X,n), "Y" = c(Y,n), ...)
where X and Y are matrices and n is an integer and the lists are of unknown size. Thanks!
If c(X,n), which coerces matrix to vector, is what you really want, then
lst <- list(a = matrix(1:4, 2), b = matrix(1:4, 2))
n <- 5
lapply(lst, c, n)
# $a
# [1] 1 2 3 4 5
#
# $b
# [1] 1 2 3 4 5