I have a list 'cats.list' with 6 elements. There are 9 unique integers that are members of one or more elements. E.g.
cats.list <- list(c(1, 2, 6), c(1, 8, 9), c(3, 4, 5, 7),
c(3, 6, 7), c(1, 3, 7, 8, 9), c(4, 5, 9))
I want to create a list with one element for each of the 9 integers in 'cats.list'. Each element in the new list should contain the list indexes in 'cat.list' for a given integer.
For example, 1 occurs in the list elements 1, 2, 5 in 'cat.list'. 2 occurs in element 1 only. 3 occurs in element 3, 4, 5. So the first three element in the new list would be:
el.list <- list(c(1, 2, 5), 1, c(3, 4, 5)...)
How can I create such a list of indexes for any 'cats.list'?
Use List Comprehension and the enumerate() Function to Get the Indices of All Occurrences of an Item in A List. Another way to find the indices of all the occurrences of a particular item is to use list comprehension. List comprehension is a way to create a new list based on an existing list.
You can make use of enumerate to get all the indexes of the element in a list. Enumerate() function is a built-in function available with python. It takes input as an iterable object (i.e., an object that can be looped), and the output is an object with a counter to each item.
The del operator removes the item or an element at the specified index location from the list, but the removed item is not returned, as it is with the pop() method.
1) reshape2 Use melt
in reshape2 to convert cats.list
into a data frame whose first column value
is the element and whose second column L1
is the corresponding component number in cats.list
that that element belongs to. Then unstack
that with the indicated formula.
library(reshape2)
unstack(melt(cats.list), L1 ~ value)
giving:
$`1`
[1] 1 2 5
$`2`
[1] 1
$`3`
[1] 3 4 5
$`4`
[1] 3 6
$`5`
[1] 3 6
$`6`
[1] 1 4
$`7`
[1] 3 4 5
$`8`
[1] 2 5
$`9`
[1] 2 5 6
2) split We could also do it this way without any packages. rep(seq_along(L), L)
equals m$L1
from (1) and unlist(cats.list)
equals m$value
from (1).
L <- lengths(cats.list)
split(rep(seq_along(L), L), unlist(cats.list))
3) stack/unstack We can also do this using only base R and stack/unstack if we name the cats.list
components.
cats.named <- setNames(cats.list, seq_along(cats.list))
unstack(stack(cats.named), ind ~ values)
We can plot this as a bipartite graph like this:
library(igraph)
library(reshape2)
m <- melt(cats.list)
M <- table(m)
g <- graph_from_incidence_matrix(M)
plot(g, layout = layout_as_bipartite)
Use -
cats.list <- list(c(1, 2, 6), c(1, 8, 9), c(3, 4, 5, 7), c(3, 6, 7),
c(1, 3, 7, 8, 9), c(4, 5, 9))
output <- c()
for(i in sort(unique(unlist(cats.list)))){
output <- c(output, list(grep(i,cats.list)))
}
Output
[[1]]
[1] 1 2 5
[[2]]
[1] 1
[[3]]
[1] 3 4 5
[[4]]
[1] 3 6
[[5]]
[1] 3 6
[[6]]
[1] 1 4
[[7]]
[1] 3 4 5
[[8]]
[1] 2 5
[[9]]
[1] 2 5 6
Explanation
unlist(cats.list)
flattens the existing list, wrapping it with unique
and sort
creates the search list with which you can iterate for the search
The magic lies in grep(i,cats.list)
, which readily gives what you want for each search.
Putting it together in an output
list is trivial. Hope that helps!
EDIT
Thanks to @ G. Grothendieck, this can be shortened to --
output <- lapply(sort(unique(unlist(cats.list))), grep, cats.list)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With