Reputation: 12087
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:
col2 = a
col2 = b
. 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
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
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