Subsetting lists of lists in R - r

How does one go about subsetting lists of lists in R?
For example I have this list:
[[6]]
[[6]][[1]]
[[6]][[1]][[1]]
[1] 111
[[6]][[2]]
[[6]][[2]][[1]]
[1] 1
[[6]][[2]][[2]]
[1] 11
[[6]][[3]]
[[6]][[3]][[1]]
[1] 11
[[6]][[3]][[2]]
[1] 1
[[6]][[4]]
[[6]][[4]][[1]]
[1] 1
[[6]][[4]][[2]]
[1] 1
[[6]][[4]][[3]]
[1] 1
and I'm trying to get all parts of the list that have 2 sublists or less. So in this example the output would be the first five sublists,
[[6]]
[[6]][[1]]
[[6]][[1]][[1]]
[1] 111
[[6]][[2]]
[[6]][[2]][[1]]
[1] 1
[[6]][[2]][[2]]
[1] 11
[[6]][[3]]
[[6]][[3]][[1]]
[1] 11
[[6]][[3]][[2]]
[1] 1

If your list is called lst, then try
lst[lengths(lst) <= 2]

Related

Print function in map behaves differently than in for loop in R

I am just practicing basic for loops to compare against their purrr::map() equivalent. However I am lost why the simple print function appears to double the output vs. its equivalent for loop.
#this simple for loop behaves as expected and gives us the numbers 1 through 10.
.x <- 1:10
for (i in .x){
print(i)
}
#result
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
#this doubles the output in an embedded list - I don't understand why
map(.x=.x,~print(.x))
#results below
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
[1] 6
[1] 7
[1] 8
[1] 9
[1] 10
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
[[5]]
[1] 5
[[6]]
[1] 6
[[7]]
[1] 7
[[8]]
[1] 8
[[9]]
[1] 9
[[10]]
[1] 10
I would have though they would produce the same (however I know the map results would be in a list unless I specify the output (eg. map_chr or map_df).
According to R documentations print prints its argument and returns it invisibly (via invisible(x)).
So your map function is essentially doing
.x <- 1:10
funcy <- function() {
out = list()
for (i in .x){
out[[i]] = print(i)
}
return(out)
}
funcy()
The print function gets called every loop and when the loop ends the function returns the stored values in a list
The purrr library has a function specifically designed for tasks such as this: walk.
If you don't want to return anything and are only calling functions for the purpose of their downstream effects (print or write_csv), you can use walk instead of map.
walk(1:10, print)
# [1] 1
# [1] 2
# [1] 3
# [1] 4
# [1] 5
# [1] 6
# [1] 7
# [1] 8
# [1] 9
# [1] 10

Replacing values in a list based on a condition

I have a list of values called squares and would like to replace all values which are 0 to a 40.
I tried:
replace(squares, squares==0, 40)
but the list remains unchanged
If it is a list, then loop through the list with lapply and use replace
squares <- lapply(squares, function(x) replace(x, x==0, 40))
squares
#[[1]]
#[1] 40 1 2 3 4 5
#[[2]]
#[1] 1 2 3 4 5 6
#[[3]]
#[1] 40 1 2 3
data
squares <- list(0:5, 1:6, 0:3)
I think for this purpose, you can just treat it as if it were a vector as follows:
squares=list(2,4,6,0,8,0,10,20)
squares[squares==0]=40
Output:
[[1]]
[1] 2
[[2]]
[1] 4
[[3]]
[1] 6
[[4]]
[1] 40
[[5]]
[1] 8
[[6]]
[1] 40
[[7]]
[1] 10
[[8]]
[1] 20

removing values from each element in a list in R

I was wondering if somebody could help with this problem. I have a list coming out from a function similar to the following:
lis<-vector("list",3)
lis[[1]]<-c(1,2,3)
lis[[2]]<-c(1,2,3)
lis[[3]]<-c(1,2,3)
so it looks like
[[1]]
[1] 1 2 3
[[2]]
[1] 1 2 3
[[3]]
[1] 1 2 3
What I want to do is remove, for example, the first element from each component of the list so it ends up like:
[[1]]
[1] 2 3
[[2]]
[1] 2 3
[[3]]
[1] 2 3
Any ideas would be most welcome.
You can use lapply() and do the index function for each element of the list. The index -1 means without the first element:
lis <- list(a=1:3, b=11:13, c=21:23)
lapply(lis, '[', -1)
# $a
# [1] 2 3
#
# $b
# [1] 12 13
#
# $c
# [1] 22 23

Constructing vectors using (nested)loops in R

I've scanned quite some fora on the internet but couldn't find a clear answer to my problem, hence I decided to post it here. The program I am using is R.
The following problem is where I can't seem to find a solution. I am tasked with constructing a vector (1,2,2,3,3,3...,10,...,10) using a nested loop (so no rep()). So far I managed to construct a list of all elements but can't manage to convert it into the desired vector. I have tried quite some methods, like converting the data into a matrix and transposing it etc.
So far not a single method has worked, perhaps someone with more insight on this matter could help me.
This is what I've got so far:
for (i in 1:10){
for (j in 1:10)
if (j<=i)
{
x = c(i)
print(x)
}
}
which provides me with:
[1] 1
[1] 2
[1] 2
[1] 3
[1] 3
[1] 3
[1] 4
[1] 4
[1] 4
[1] 4
[1] 5
[1] 5
[1] 5
[1] 5
[1] 5
[1] 6
[1] 6
[1] 6
[1] 6
[1] 6
[1] 6
[1] 7
[1] 7
[1] 7
[1] 7
[1] 7
[1] 7
[1] 7
[1] 8
[1] 8
[1] 8
[1] 8
[1] 8
[1] 8
[1] 8
[1] 8
[1] 9
[1] 9
[1] 9
[1] 9
[1] 9
[1] 9
[1] 9
[1] 9
[1] 9
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
[1] 10
Thanks in advance!
If storing the result in a vector, instead of printing it, is the remaining problem, this can be done this way:
result <- vector(mode = "integer")
k <- 1
for (i in 1:10){
for (j in 1:10)
if (j<=i)
{
result[k] = c(i)
k <- k+1
}
}
head(result)

adding a field to each element of a list

I have a list
> (mylist <- list(list(a=1),list(a=2),list(a=3)))
[[1]]
[[1]]$a
[1] 1
[[2]]
[[2]]$a
[1] 2
[[3]]
[[3]]$a
[1] 3
and I want to add field b to each sublist from 11:13 to get something like
> (mylist <- list(list(a=1,b=11),list(a=2,b=12),list(a=3,b=13)))
[[1]]
[[1]]$a
[1] 1
[[1]]$b
[1] 11
[[2]]
[[2]]$a
[1] 2
[[2]]$b
[1] 12
[[3]]
[[3]]$a
[1] 3
[[3]]$b
[1] 13
How do I do this?
(note that I have a large number of such relatively small lists, so this will be called in apply and has to be reasonably fast).
mylist <- list(list(a=1),list(a=2),list(a=3))
b.vals <- 11:13
mylist <- lapply(
1:length(mylist),
function(x) {
mylist[[x]]$b <- b.vals[[x]]
mylist[[x]]
} )

Resources