Niyas
Niyas

Reputation: 515

Filtering list in R

I have a list

  A <- c(1,2,3,4,5,6,7,8,9,10)
  B <- c("a" ,"b", "c" ,"d","b" ,"f" ,"g" ,"a" ,"b" ,"a")
  C <- c(25, 26, 27, 28, 29, 30, 31, 32, 10, 15)
  mylist <- list(A,B,C)
  mylist  
  [[1]]
  [1]  1  2  3  4  5  6  7  8  9 10

  [[2]]
  [1] "a" "b" "c" "d" "b" "f" "g" "a" "b" "a" 

  [[3]]
  [1] 25 26 27 28 29 30 31 32 10 15

I would like to select all components A,B,C of the list where second component B has value "a" or "b" .

Sample output

  mylist  
  [[1]]
  [1]  1  2  6  8  9 10

  [[2]]
  [1] "a" "b" "b" "a" "b" "a" 

  [[3]]
  [1] 25 26 29 32 10 15

How can I do that? Note that each component have same length.

Upvotes: 0

Views: 10666

Answers (3)

Colonel Beauvel
Colonel Beauvel

Reputation: 31181

To stay with a list, why not simply:

lapply(mylist, `[`, is.element(B, letters[1:2]))
#[[1]]
#[1]  1  2  5  8  9 10

#[[2]]
#[1] "a" "b" "b" "a" "b" "a"

#[[3]]
#[1] 25 26 29 32 10 15

Upvotes: 5

Tensibai
Tensibai

Reputation: 15784

I would go with a data.frame or data.table for this use case:

Using your original list (with a 10 added to A to have the same number of entries as B and C):

>df <- data.frame(A=mylist[[1]],B=mylist[[2]],C=mylist[[3]],stringsAsFactors=F)
> df[df$B %in% c("a","b"),]
    A B  C
1   1 a 25
2   2 b 26
5   5 b 29
8   8 a 32
9   9 b 10
10 10 a 15

This will subset the data.frame by where B values are a or b. If you build your list at first, you may avoid the list step and build the data.frame directly.

If you really want a list at end:

> as.list(df[df$B %in% c("a","b"),])
$A
[1]  1  2  5  8  9 10

$B
[1] "a" "b" "b" "a" "b" "a"

$C
[1] 25 26 29 32 10 15

If you wish to avoid the named entries, use unname: as.list(unname(df[..]))

Upvotes: 3

PAC
PAC

Reputation: 5376

Here is a simple solution.

First, I create mylist :

mylist <- list(1:10, letters[1:10], 25:15)

Then I create a function which returns TRUE if the condition is TRUE and FALSE otherwise

> filt <- function(x) {
+   x[2] %in% c("a", "b")
+ }
> 

Then I use sapply to apply the function to mylist and I select only the components I need :

> mylist[sapply(mylist, filt) == TRUE]
[[1]]
[1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

Upvotes: 2

Related Questions