Преобразовать список значений в список индексов списка для каждого значения - PullRequest
0 голосов
/ 24 ноября 2018

У меня есть список 'cats.list' с 6 элементами.Есть 9 уникальных целых чисел, которые являются членами одного или нескольких элементов.Например,

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))

Я хочу создать список с одним элементом для каждого из 9 целых чисел в 'cats.list'.Каждый элемент в новом списке должен содержать индексы списка в 'cat.list' для данного целого числа.

Например, 1 встречается в элементах списка 1, 2, 5 в 'cat.list'.2 встречается только в элементе 1.3 встречается в элементах 3, 4, 5. Таким образом, первые три элемента в новом списке будут:

el.list <- list(c(1, 2, 5), 1, c(3, 4, 5)...) 

Как я могу создать такой список индексов для любого 'cats.list'?

Ответы [ 4 ]

0 голосов
/ 26 ноября 2018

Тидиверс версия:

tibble(cats.list) %>% 
  rowid_to_column() %>% 
  unnest %>%
  group_by(cats.list) %>%
  summarize_at("rowid", list) %>%
  pull(rowid)
# [[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
# 
0 голосов
/ 24 ноября 2018

1) reshape2 Используйте melt в reshape2 для преобразования cats.list во фрейм данных, первый столбец которого value является элементом, а второй столбец L1 - соответствующий номер компонента в cats.list что этот элемент принадлежит.Затем unstack, что с указанной формулой.

library(reshape2)

unstack(melt(cats.list), L1 ~ value)

, дающей:

$`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 Мы могли бы сделать это также без каких-либо пакетов.rep(seq_along(L), L) равно m$L1 из (1) и unlist(cats.list) равно m$value из (1).

L <- lengths(cats.list)
split(rep(seq_along(L), L), unlist(cats.list))

3) stack / unstack Мы также можем сделать это, используятолько базовая R и стек / unstack, если мы назовем cats.list компоненты.

cats.named <- setNames(cats.list, seq_along(cats.list))
unstack(stack(cats.named), ind ~ values)

Примечание

Мы можем построить это в виде двудольного графа, например:

library(igraph)
library(reshape2)

m <- melt(cats.list)
M <- table(m)
g <- graph_from_incidence_matrix(M)
plot(g, layout = layout_as_bipartite)

screenshot

0 голосов
/ 24 ноября 2018

Просто для округления доступных опций здесь, версия, которая использует два вызова sapply/lapply вместо for loop и grep:

sapply(sort(unique(unlist(cats.list))), function(x) {
  idx <- sapply(cats.list, function(y) any(y == x))
  return(which(idx))
})

[[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
0 голосов
/ 24 ноября 2018

Использование -

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)))
}

Вывод

[[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

Пояснение

unlist(cats.list) сглаживает существующий списокОбтекание его unique и sort создает список поиска, с которым вы можете перебирать поиск

Магия заключается в grep(i,cats.list), который с готовностью дает то, что вы хотите для каждого поиска.

Собрать его в список output тривиально.Надеюсь, это поможет!

РЕДАКТИРОВАТЬ

Благодаря @ G. Grothendieck, это может быть сокращено до -

output <- lapply(sort(unique(unlist(cats.list))), grep, cats.list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...