user9798936
user9798936

Reputation:

How to remove zero vectors from a list of list in r

Problem:

I have a list of two lists of three vectors. I would like to remove the zero vector from each sublist.

Example:

x <- list(x1=c(0,0,0), x2=c(3,4,5), x3=c(45,34,23))
y <- list(y1=c(2,33,4), y2=c(0,0,0), y3=c(4,5,44))
z <- list(x, y)

Try:

I tried this:

res <- lapply(1:2, function(i) {lapply(1:3, function(j) z[[i]][[j]][z[[i]][[j]] != 0])})

Which gave me this:

> res
[[1]]
[[1]][[1]]
numeric(0)

[[1]][[2]]
[1] 3 4 5

[[1]][[3]]
[1] 45 34 23


[[2]]
[[2]][[1]]
[1]  2 33  4

[[2]][[2]]
numeric(0)

[[2]][[3]]
[1]  4  5 44

Problem with the output:

I do not want numeric(0).

Expected output:

x= list(x2, x3)
y=list(y1, y3)

Any idea, please?

Upvotes: 2

Views: 2178

Answers (5)

moodymudskipper
moodymudskipper

Reputation: 47300

with purrr it can be really compact

library(purrr)
map(z, keep ,~all(.!=0))
# [[1]]
# [[1]]$x2
# [1] 3 4 5
# 
# [[1]]$x3
# [1] 45 34 23
# 
# 
# [[2]]
# [[2]]$y1
# [1]  2 33  4
# 
# [[2]]$y3
# [1]  4  5 44

If it wasn't for the annoying warnings we could do just map(z, keep , all)

Upvotes: 0

r.user.05apr
r.user.05apr

Reputation: 5456

Or:

x <- list(x1=c(0,0,0), x2=c(3,4,5), x3=c(45,34,23))
y <- list(y1=c(2,33,4), y2=c(0,0,0), y3=c(4,5,44))
z <- list(x, y)

lapply(z, function(a) a[unlist(lapply(a, function(b) !identical(b, rep(0,3))))])

#[[1]]
#[[1]]$`x2`
#[1] 3 4 5
#
#[[1]]$x3
#[1] 45 34 23
#
#
#[[2]]
#[[2]]$`y1`
#[1]  2 33  4
#
#[[2]]$y3
#[1]  4  5 44

Upvotes: 0

Patrik_P
Patrik_P

Reputation: 3200

Given your structure of list of lists I would go with the following:

filteredList <- lapply(z, function(i) Filter(function(x) any(x != 0), i))

x <- filteredList[[1]]
y <- filteredList[[2]]

x
##$`x2`
##[1] 3 4 5

##$x3
##[1] 45 34 23
y
##$`y1`
##[1]  2 33  4

##$y3
##[1]  4  5 44

Upvotes: 1

Andre Elrico
Andre Elrico

Reputation: 11480

define z as

z <- c(x, y)
# z <- unlist(z, recursive = F)  if you cannot define z by yourself.

then use:

z[sapply(z, any)]

#$`x2`
#[1] 3 4 5

#$x3
#[1] 45 34 23

#$y1
#[1]  2 33  4

#$y3
#[1]  4  5 44

Please note:

As in the tradition of lang C. Every integer/ numeric != 0 will be casted to TRUE. So in this task we can use this logic. ?any will eval FALSE if all values are 0.

Upvotes: 0

Roman
Roman

Reputation: 17648

You can try a tidyverse if the nested list structure is not important

library(tidyverse)
z %>% 
  flatten() %>% 
  keep(~all(. != 0))
$x2
[1] 3 4 5

$x3
[1] 45 34 23

$y1
[1]  2 33  4

$y3
[1]  4  5 44

Upvotes: 3

Related Questions