compute all permutation with repetition of list R - r

i have this list of vector out:
[[1]]
[1] (1,5)(3)(4)(6)
[[2]]
[1] (3,6)(1)(4)(5)
[[3]]
[1] (3,4)(1)(5)(6)
[[4]]
[1] (3,5)(1)(4)(6)
[[5]]
[1] (4,6)(1)(3)(5)
[[5]]
[1] (4,5)(1)(3)(6)
[[6]]
[1] (5,6)(1)(3)(4)
take one elemente for example out[[5]] (4,6)(1)(3)(5), i would generate all permutation of element with all possible order, for example:
{(4,6)(3)(1)(5)},{(3)(4,6)(5)(1)}...

I think this is what the OP is looking for:
out <- list(c("(1,5)","(3)","(4)","(6)"), c("(3,6)","(1)","(4)","(5)"),
c("(3,4)","(1)","(5)","(6)"),c("(3,5)","(1)","(4)","(6)"),
c("(4,6)","(1)","(3)","(5)"), c("(4,5)","(1)","(3)","(6)"),
c("(5,6)","(1)","(3)","(4)"))
library(RcppAlgos)
myPerms <- lapply(out, function(x) {
unlist(permuteGeneral(x, length(x), FUN = function(y) {
paste0(c("{", y, "}"), collapse = "")
}))
})
We use permuteGeneral from RcppAlgos (I am the author) as we can utilize the FUN argument to pass a custom function that will be applied to each permutation (i.e. paste0(c("{", y, "}"), collapse = "")).
Here is the output of the 5th element:
myPerms[[5]]
[1] "{(4,6)(1)(3)(5)}" "{(4,6)(1)(5)(3)}" "{(4,6)(3)(1)(5)}"
[4] "{(4,6)(3)(5)(1)}" "{(4,6)(5)(1)(3)}" "{(4,6)(5)(3)(1)}"
[7] "{(1)(4,6)(3)(5)}" "{(1)(4,6)(5)(3)}" "{(1)(3)(4,6)(5)}"
[10] "{(1)(3)(5)(4,6)}" "{(1)(5)(4,6)(3)}" "{(1)(5)(3)(4,6)}"
[13] "{(3)(4,6)(1)(5)}" "{(3)(4,6)(5)(1)}" "{(3)(1)(4,6)(5)}"
[16] "{(3)(1)(5)(4,6)}" "{(3)(5)(4,6)(1)}" "{(3)(5)(1)(4,6)}"
[19] "{(5)(4,6)(1)(3)}" "{(5)(4,6)(3)(1)}" "{(5)(1)(4,6)(3)}"
[22] "{(5)(1)(3)(4,6)}" "{(5)(3)(4,6)(1)}" "{(5)(3)(1)(4,6)}"
If you really want permutations with repetition, simply set repetition = TRUE in permuteGeneral. Of course, if you want a more useable output, we can drop the custom FUN altogether.
UPDATE
After learning more about how the OP obtained out above, we can better attack the problem. First we find out that the OP uses listParts from the library partitions. Looking at the source code we have:
listParts
function (x)
{
f <- function(pp) {
out <- split(seq_along(pp), pp)
class(out) <- c(class(out), "equivalence")
out
}
apply(setparts(x), 2, f)
}
<bytecode: 0x10d7b09f8>
<environment: namespace:partitions>
We can alter this to obtain all permutations:
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)
}
We note that we are going against the intent of listParts... quoting the documentation:
"Note that (12)(3)(4) is the same partition as, for example, (3)(4)(21) as the equivalence relation is the same."
Oh well... here is the output for permutations of length 3:
permListParts(3)
[[1]]
[[1]][[1]]
[1] (1,2,3)
[[2]]
[[2]][[1]]
[1] (1,3)(2)
[[2]][[2]]
[1] (2)(1,3)
[[3]]
[[3]][[1]]
[1] (1,2)(3)
[[3]][[2]]
[1] (3)(1,2)
[[4]]
[[4]][[1]]
[1] (2,3)(1)
[[4]][[2]]
[1] (1)(2,3)
[[5]]
[[5]][[1]]
[1] (1)(2)(3)
[[5]][[2]]
[1] (1)(3)(2)
[[5]][[3]]
[1] (2)(1)(3)
[[5]][[4]]
[1] (2)(3)(1)
[[5]][[5]]
[1] (3)(1)(2)
[[5]][[6]]
[1] (3)(2)(1)

You could try this:
test <- list(list(1,5),3,4,6)
combn(test,2)
> combn(test,2)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] List,2 List,2 List,2 3 3 4
[2,] 3 4 6 4 6 6
This would give you all the possible combinations of 2 elements from your list. If you want to do that for each element of your main list you can then use a for or lapply on it.
try:
lapply(out, function(x) combn(x,2))

How about gtools packages
out <- list(
c(1.5,3,4,6),
c(3.6,1,4,5),
c(3.4,1,5,6),
c(3.5,1,4,6),
c(4.6,1,3,5),
c(4.5,1,3,6),
c(5.6,1,3,4))
require(gtools)
allPerm <- function(x){
return(permutations(length(x), length(x), x))
}

Related

r extract element from the list with for-loop

I have the following list of values:
$`1`
[1] "S21_027_1" "5_G3_A_1_counts.txt"
$`5`
[1] "S21_027_13" "5_G3_A_12_counts.txt"
$`9`
[1] "S21_027_17" "5_G3_A_15_counts.txt"
$`14`
[1] "S21_027_21" "5_G3_A_22_counts.txt"
$`18`
[1] "S21_027_25" "5_G3_A_26_counts.txt"
$`22`
[1] "S21_027_29" "5_G3_A_29_counts.txt"
I try to extract only stuff which starts with S21_027.
I tried to use for loop however it keeps just one element.
My attempt to extract it:
order_column <- c()
for (i in length(order_col))
{
v <- order_col[[i]][[1]]
print(v)
order_column <- c(v, order_column)
}
Using base R
lapply(order_col, grep, pattern = 'S21_027', value = TRUE)
[[1]]
[1] "S21_027_1"
[[2]]
[1] "S21_027_13"
[[3]]
[1] "S21_027_17"
Does this work:
lst <- list(c('S21_027_1','5_G3_A_1_counts.txt'),
c('S21_027_13','5_G3_A_12_counts.txt'),
c('S21_027_17','5_G3_A_15_counts.txt'))
sapply(lst, function(x) x[grepl('^S21_027', x)])
[1] "S21_027_1" "S21_027_13" "S21_027_17"
You may use -
library(purrr)
library(stringr)
map(order_col, str_subset, "S21_027")
#[[1]]
#[1] "S21_027_1"
#[[2]]
#[1] "S21_027_13"
#[[3]]
#[1] "S21_027_17"
Or to extract the 1st element -
map_chr(order_col, head, 1)
#[1] "S21_027_1" "S21_027_13" "S21_027_17"

How to store multiple for loops with nested lists?

I am trying to store a nested for loop outcome but I find it hard to do so. This is what I have:
library("pageviews")
lang = c("it.wikipedia", "de.wikipedia", "fr.wikipedia", "es.wikipedia")
bm = c("ECB","Christine Lagarde")
x = list(list()) # store results
for (i in 1:length(lang)) {
for (j in 1:length(bm)) {
x[[i]][[j]] = article_pageviews(project = lang[i], article = bm[j], platform = "all", user_type = "user", start = "2015100100", end = today(), reformat = TRUE, granularity = "daily")
}
}
x = do.call(rbind, x) # from list to df
What I would like to do is to run the code for each lang and article and store it accordingly. So I would have a list with it.wikipedia for ECB, it.wikipedia for Lagarde, etc...
Can anyone help me do it?
Thanks!
If you are stuck at creating nested list via nested for loops, perhaps the code example below could help
a <- letters[1:5]
b <- LETTERS[1:5]
x <- c()
for (i in seq_along(a)) {
u <- c()
for (j in seq_along(b)) {
u <- c(u, list(paste0(a[i], "-", b[j])))
}
x <- c(x, list(u))
}
where u and x are used to gather lists at different layers, such that
> x
[[1]]
[[1]][[1]]
[1] "a-A"
[[1]][[2]]
[1] "a-B"
[[1]][[3]]
[1] "a-C"
[[1]][[4]]
[1] "a-D"
[[1]][[5]]
[1] "a-E"
[[2]]
[[2]][[1]]
[1] "b-A"
[[2]][[2]]
[1] "b-B"
[[2]][[3]]
[1] "b-C"
[[2]][[4]]
[1] "b-D"
[[2]][[5]]
[1] "b-E"
[[3]]
[[3]][[1]]
[1] "c-A"
[[3]][[2]]
[1] "c-B"
[[3]][[3]]
[1] "c-C"
[[3]][[4]]
[1] "c-D"
[[3]][[5]]
[1] "c-E"
[[4]]
[[4]][[1]]
[1] "d-A"
[[4]][[2]]
[1] "d-B"
[[4]][[3]]
[1] "d-C"
[[4]][[4]]
[1] "d-D"
[[4]][[5]]
[1] "d-E"
[[5]]
[[5]][[1]]
[1] "e-A"
[[5]][[2]]
[1] "e-B"
[[5]][[3]]
[1] "e-C"
[[5]][[4]]
[1] "e-D"
[[5]][[5]]
[1] "e-E"
Yes, you would need a nested loop. One way to do that using map_df from purrr.
library(purrr)
map_df(lang, function(x) map_df(bm, function(y)
article_pageviews(project = x, article = y, platform = "all", user_type = "user",
start = "2015100100", end = today(), reformat = TRUE, granularity = "daily"))) -> result
So, your approach is correct. But you forgot some things; you want to store for each language, two articles.
Therefore you need 4 lists, such that,
x <- list(
list(),
list(),
list(),
list()
)
And as your lists are nested, you need to undo this by using purrr::flatten(), such that,
x <- do.call(rbind, purrr::flatten(x)) # from list to df
After your for-loop

How to find NULL in nested lists [duplicate]

How do I remove the null elements from a list of lists, like below, in R:
lll <- list(list(NULL),list(1),list("a"))
The object I want would look like:
lll <- list(list(1),list("a"))
I saw a similar answer here: How can I remove an element from a list? but was not able to extend it from simple lists to a list of lists.
EDIT
Bad example above on my part. Both answers work on simpler case (above). What if list is like:
lll <- list(list(NULL),list(1,2,3),list("a","b","c"))
How to get:
lll <- list(list(1,2,3),list("a","b","c"))
This recursive solution has the virtue of working on even more deeply nested lists.
It's closely modeled on Gabor Grothendieck's answer to this quite similar question. My modification of that code is needed if the function is to also remove objects like list(NULL) (not the same as NULL), as you are wanting.
## A helper function that tests whether an object is either NULL _or_
## a list of NULLs
is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))
## Recursively step down into list, removing all such objects
rmNullObs <- function(x) {
x <- Filter(Negate(is.NullOb), x)
lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}
rmNullObs(lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Here is an example of its application to a more deeply nested list, on which the other currently proposed solutions variously fail.
LLLL <- list(lll)
rmNullObs(LLLL)
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [[1]][[1]][[1]][[1]]
# [1] 1
#
#
# [[1]][[1]][[2]]
# [[1]][[1]][[2]][[1]]
# [1] "a"
Here's an option using Filter and Negate combination
Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Using purrr
purrr::map(lll, ~ purrr::compact(.)) %>% purrr::keep(~length(.) != 0)
[[1]]
[[1]][[1]]
[1] 1
[[1]][[2]]
[1] 2
[[1]][[3]]
[1] 3
[[2]]
[[2]][[1]]
[1] "a"
[[2]][[2]]
[1] "b"
[[2]][[3]]
[1] "c"
For this particular example you can also use unlist with its recursive argument.
lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Since you have lists in lists, you probably need to run l/sapply twice, like:
lll[!sapply(lll,sapply,is.null)]
#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
There is a new package rlist on CRAN, thanks to Kun Ren for making our life easier.
list.clean(.data, fun = is.null, recursive = FALSE)
or for recursive removal of NULL:
list.clean(.data, fun = is.null, recursive = TRUE)
Quick fix on Josh O'Brien's solution. There's a bit of an issue with lists of functions
is.NullOb <- function(x) if(!(is.function(x))) is.null(x) | all(sapply(x, is.null)) else FALSE
## Recursively step down into list, removing all such objects
rmNullObs <- function(x) {
if(!(is.function(x))) {
x = x[!(sapply(x, is.NullOb))]
lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}
}

R - lapply several functions in one lapply by elements

In R, when I run two functions in lapply, it runs the first function on the entire list, then run the second function on the list. Is it possible to force it runs both functions on the first element on the list before moving onto the second element?
I am using the function print and nchar for illustration purpose -- I wrote more complex functions that generate data.frame.
lapply(c("a","bb","cdd"), function(x) {
print(x)
nchar(x)
})
the output would be
[1] "a"
[1] "bb"
[1] "cdd"
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
I would like to have something like this:
[[1]]
[1] "a"
[1] 1
[[2]]
[1] "bb"
[1] 2
[[3]]
[1] "cdd"
[1] 3
is this possible?
Juan Antonio Roladan Diaz and cash2 both suggested using list, which kind of works:
lapply(c("a","bb","cdd"), function(x) {
list(x, nchar(x))
})
[[1]]
[[1]][[1]]
[1] "a"
[[1]][[2]]
[1] 1
[[2]]
[[2]][[1]]
[1] "bb"
[[2]][[2]]
[1] 2
[[3]]
[[3]][[1]]
[1] "cdd"
[[3]][[2]]
[1] 3
But it is a bit too messy.
using print gives a better result,
lapply(c("a","bb","cdd"), function(x) {
print(x)
print(nchar(x))
})
[1] "a"
[1] 1
[1] "bb"
[1] 2
[1] "cdd"
[1] 3
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
but is there a way to suppress nchar from being print out again?
invisible(lapply(c("a","bb","cdd"), function(x) { print(x); print(nchar(x)) }))
This happens because the function prints x, then returns nchar(x); the returned elements are put into a list by lapply and returned, and printed out on the REPL.
Replace nchar(x) with print(nchar(x)). Or, if you want the list returned, just return list(x, nchar(x)) from the inner function.

Remove NULL elements from list of lists

How do I remove the null elements from a list of lists, like below, in R:
lll <- list(list(NULL),list(1),list("a"))
The object I want would look like:
lll <- list(list(1),list("a"))
I saw a similar answer here: How can I remove an element from a list? but was not able to extend it from simple lists to a list of lists.
EDIT
Bad example above on my part. Both answers work on simpler case (above). What if list is like:
lll <- list(list(NULL),list(1,2,3),list("a","b","c"))
How to get:
lll <- list(list(1,2,3),list("a","b","c"))
This recursive solution has the virtue of working on even more deeply nested lists.
It's closely modeled on Gabor Grothendieck's answer to this quite similar question. My modification of that code is needed if the function is to also remove objects like list(NULL) (not the same as NULL), as you are wanting.
## A helper function that tests whether an object is either NULL _or_
## a list of NULLs
is.NullOb <- function(x) is.null(x) | all(sapply(x, is.null))
## Recursively step down into list, removing all such objects
rmNullObs <- function(x) {
x <- Filter(Negate(is.NullOb), x)
lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}
rmNullObs(lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Here is an example of its application to a more deeply nested list, on which the other currently proposed solutions variously fail.
LLLL <- list(lll)
rmNullObs(LLLL)
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [[1]][[1]][[1]][[1]]
# [1] 1
#
#
# [[1]][[1]][[2]]
# [[1]][[1]][[2]][[1]]
# [1] "a"
Here's an option using Filter and Negate combination
Filter(Negate(function(x) is.null(unlist(x))), lll)
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Using purrr
purrr::map(lll, ~ purrr::compact(.)) %>% purrr::keep(~length(.) != 0)
[[1]]
[[1]][[1]]
[1] 1
[[1]][[2]]
[1] 2
[[1]][[3]]
[1] 3
[[2]]
[[2]][[1]]
[1] "a"
[[2]][[2]]
[1] "b"
[[2]][[3]]
[1] "c"
For this particular example you can also use unlist with its recursive argument.
lll[!sapply(unlist(lll, recursive=FALSE), is.null)]
# [[1]]
# [[1]][[1]]
# [1] 1
#
#
# [[2]]
# [[2]][[1]]
# [1] "a"
Since you have lists in lists, you probably need to run l/sapply twice, like:
lll[!sapply(lll,sapply,is.null)]
#[[1]]
#[[1]][[1]]
#[1] 1
#
#
#[[2]]
#[[2]][[1]]
#[1] "a"
There is a new package rlist on CRAN, thanks to Kun Ren for making our life easier.
list.clean(.data, fun = is.null, recursive = FALSE)
or for recursive removal of NULL:
list.clean(.data, fun = is.null, recursive = TRUE)
Quick fix on Josh O'Brien's solution. There's a bit of an issue with lists of functions
is.NullOb <- function(x) if(!(is.function(x))) is.null(x) | all(sapply(x, is.null)) else FALSE
## Recursively step down into list, removing all such objects
rmNullObs <- function(x) {
if(!(is.function(x))) {
x = x[!(sapply(x, is.NullOb))]
lapply(x, function(x) if (is.list(x)) rmNullObs(x) else x)
}
}

Resources