Denis
Denis

Reputation: 12087

Split a list of vectors based on named attribute in vector

I am looking for a way to split a list of vectors based on a named attribute in a vector. Suppose I have a named list with vectors:

> v <- list("1"=c(col1=1, col2="a", col3="!"), "2"=c(col1=2, col2="b", col3="@"), "3"=c(col1=3, col2="b", col3="#"), "4"=c(col1=4, col2="a", col3="$"))
> v
$`1`
col1 col2 col3 
 "1"  "a"  "!" 

$`2`
col1 col2 col3 
 "2"  "b"  "@" 

$`3`
col1 col2 col3 
 "3"  "b"  "#" 

$`4`
col1 col2 col3 
 "4"  "a"  "$" 

I would like to split out based on the value of col2 for example so in this example I would like to have 2 lists:


I am looking for the output to be similar to the following:

For col2 = a:

$`1`
col1 col2 col3 
 "1"  "a"  "!" 
$`4`
col1 col2 col3 
 "4"  "a"  "$" 

For col2 = b:

$`2`
col1 col2 col3 
 "2"  "b"  "@" 

$`3`
col1 col2 col3 
 "3"  "b"  "#" 

NOTE: I would prefer a more generalized solution that groups by col2 but a binary solution would be OK because in this particular application I only have 2 possible values for col2.

Upvotes: 4

Views: 153

Answers (2)

www
www

Reputation: 39184

A solution using split and sapply.

split(v, sapply(v, function(x) x[["col2"]]))
# $a
# $a$`1`
# col1 col2 col3 
# "1"  "a"  "!" 
# 
# $a$`4`
# col1 col2 col3 
# "4"  "a"  "$" 
# 
# 
# $b
# $b$`2`
# col1 col2 col3 
# "2"  "b"  "@" 
# 
# $b$`3`
# col1 col2 col3 
# "3"  "b"  "#" 

Upvotes: 3

Sotos
Sotos

Reputation: 51612

You can rbind first, i.e.

d1 <- data.frame(do.call(rbind, v))
split(d1, d1$col2)

which gives,

$`a`
  col1 col2 col3
1    1    a    !
4    4    a    $

$b
  col1 col2 col3
2    2    b    @
3    3    b    #

If you wish to re-split on every row, then you can do,

lapply(split(d1, d1$col2), function(i)split(i, seq(nrow(i))))

which gives,

$`a`
$`a`$`1`
  col1 col2 col3
1    1    a    !

$`a`$`2`
  col1 col2 col3
4    4    a    $


$b
$b$`1`
  col1 col2 col3
2    2    b    @

$b$`2`
  col1 col2 col3
3    3    b    #

Upvotes: 2

Related Questions