[R] Split a vector(list) into 3 list
Marc Schwartz
marc_schwartz at comcast.net
Fri May 18 02:47:18 CEST 2007
On Thu, 2007-05-17 at 17:14 -0700, Patrick Wang wrote:
> Hi,
>
> I have a vector contains values 1,2,3.
>
> Can I call a function split to split it into 3 vectors with 1 corresponds
> to value ==1, which contain all the indexes for value==1.
>
> 2 corresponds to value ==2 which contain all the indexes for value=2
>
> Thanks
> pat
Let's first try with unequal numbers of each value:
set.seed(1)
Vec <- sample(3, 20, replace = TRUE)
> Vec
[1] 1 2 2 3 1 3 3 2 2 1 1 1 3 2 3 2 3 3 2 3
> sapply(1:3, function(x) which(Vec == x))
[[1]]
[1] 1 5 10 11 12
[[2]]
[1] 2 3 8 9 14 16 19
[[3]]
[1] 4 6 7 13 15 17 18 20
Now let's try with equal counts of each number:
Vec <- sample(rep(1:3, each = 5))
> Vec
[1] 3 1 2 1 3 1 1 2 2 3 2 1 3 3 2
> t(sapply(1:3, function(x) which(Vec == x)))
[,1] [,2] [,3] [,4] [,5]
[1,] 2 4 6 7 12
[2,] 3 8 9 11 15
[3,] 1 5 10 13 14
Note how the result varies in structure depending upon the content of
the source vector. In the first case you get a list, in the second a
matrix.
If you wish you could add code to set names for the list elements or
rownames for the matrix, which can help with comprehension of the result
if you have other, non-sequential values, etc.
Res <- sapply(1:3, function(x) which(Vec == x))
names(Res) <- 1:3
> Res
$`1`
[1] 1 5 10 11 12
$`2`
[1] 2 3 8 9 14 16 19
$`3`
[1] 4 6 7 13 15 17 18 20
mat <- t(sapply(1:3, function(x) which(Vec == x)))
rownames(mat) <- 1:3
> mat
[,1] [,2] [,3] [,4] [,5]
1 2 4 6 7 12
2 3 8 9 11 15
3 1 5 10 13 14
See ?sapply and ?which
Also, to make the approach more generic, you could use:
unique(Vec)
to get the unique values in the source vector and then use that result
for the first argument in sapply() and then for the names in the result.
For example:
Vals <- unique(Vec)
Res <- sapply(Vals, function(x) which(Vec == x))
names(Res) <- Vals
See ?unique
HTH,
Marc Schwartz
More information about the R-help
mailing list