Related
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"
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 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)
}
}
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))
}
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)
}
}