Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert list of values to a list of list indexes for each value

Tags:

r

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'?

like image 415
SteveM Avatar asked Nov 24 '18 19:11

SteveM


People also ask

How do I get a list of indexes in a 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.

How do I get a list of indices in Python?

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.

Which operator is used to get an element out of a list by index?

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.


2 Answers

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)

Note

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)

screenshot

like image 50
G. Grothendieck Avatar answered Oct 17 '22 05:10

G. Grothendieck


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)
like image 24
Vivek Kalyanarangan Avatar answered Oct 17 '22 04:10

Vivek Kalyanarangan