У меня есть следующий список:
> list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
[[1]]
[1] 3 4 5 8
[[2]]
[1] 2 6 9 10
[[3]]
[1] 1 7
Таким образом, мы можем сказать, что 3 принадлежит группе 1, 6 принадлежит группе 2, 7 принадлежит группе 3 и так далее. Мне нужно обратное сопоставление, то есть для каждого числа, которому я хочу иметь идентификатор группы, к которой он принадлежит (см. Ожидаемый результат):
> list(3, 2, 1, 1, 1, 2, 3, 1, 2, 2)
[[1]]
[1] 3
[[2]]
[1] 2
[[3]]
[1] 1
[[4]]
[1] 1
[[5]]
[1] 1
[[6]]
[1] 2
[[7]]
[1] 3
[[8]]
[1] 1
[[9]]
[1] 2
[[10]]
[1] 2
Я думал, что purrr::transpose должен сделать эту работу, но он не совсем то, что я намеревался, не так ли? Как это сделать?
PS. В конечном итоге мне нужен только вектор формы: 3 2 1 1 1 2 3 1 2 2, но, имея выше, я думаю, что unlist() достаточно для преобразования.
@PKumar: 1 в группе 3, 2 в группе 2, 3 в группе 1, 4 в группе 1, 5 в группе 1 ...
Мы начинаем с 1 и смотрим, к какой группе 1 принадлежит - мы видим, что это в 3-й группе, а именно в 3-м элементе списка. Затем мы идем с 2:10 и проверяем то же самое.





Вот базовое решение ...
list <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
rep(1:length(list), sapply(list, length))[order(unlist(list))]
Хорошее решение, вы можете полностью векторизовать это с помощью rep(seq_along(l), lengths(l))[order(unlist(l))] (не уверен, для чего вы используете as.numeric).
По поводу «не совсем отвечает на мой главный вопрос с преобразованием списка наизнанку», думаю, вам нужно уточнить свой вопрос. То, как вы описываете и представляете желаемый результат, кажется, что вы просто хотите получить индекс списка для каждого значения (чего достигают этот и другие ответы). Я не вижу «вывернутой наизнанку» части;)
@DavidArenburg Хороший замечание (исходное решение было немного длиннее, так что это был всего лишь шум ;-))
Проверьте это решение:
library(tidyverse)
library(magrittr)
library(wrapr)
list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7)) %.>%
tibble(x = .) %>%
mutate(rn = row_number()) %>%
unnest() %>%
arrange(x) %$%
set_names(rn, x) %>%
as.list()
5-я строчка это ошибка %.>%?
Нет. Это труба из упаковки wrapr.
Почему вы дополнительно используете %.>% в оболочке вместо использования %>% в tidyverse? В этом случае они получат такой же результат.
x <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
Следующие 3 формы получат одинаковые результаты:
library(tidyverse)
# (1)
x %>% set_names(1:3) %>% stack %>% arrange(values) %>% select(ind)
# (2)
x %>% enframe %>% unnest %>% arrange(value) %>% select(name)
# (3)
x %>% (reshape2::melt) %>% arrange(value) %>% select(L1)
Могу я предложить старомодный цикл:
# your list
x <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
# the data in the list as vector
num <- unlist( x )
# the variable that will be the position vector
pos <- NULL
# loop through the possible position, see which number it contains
# find which "group it belongs to, and add that finding to the position vector
for( i in 1:length( num ) )
for( j in 1:length( x ) )
if ( i %in% x[[j]] ) pos <- c( pos, j )
pos
[1] 3 2 1 1 1 2 3 1 2 2
Также в base примерно так
L <- as.list(setNames( rep(1:length(lengths(l)), lengths(l)), unlist(l)))
# if wanted, sort it with
L[as.character(sort(as.integer(names(L))))]
# if wanted, unname with
unname(L)
с l <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7)).
Или завернутый в функцию
list_inside_out <- function (l, unName = TRUE) {
l2 <- lengths(l)
out <- as.list(setNames(rep(1:length(l2), l2), unlist(l)))
out <- out[as.character(sort(as.integer(names(out))))]
if (unName) return(unname(out))
out
}
list_inside_out(l)
# [[1]]
# [1] 3
#
# [[2]]
# [1] 2
#
# [[3]]
# [1] 1
# ...
Решение с использованием purrr. dat2 - это конечный результат, целочисленный вектор.
dat <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
library(purrr)
dat2 <- dat %>%
imap(~set_names(.x, rep(.y, length(.x)))) %>%
unlist() %>%
sort() %>%
names() %>%
as.integer()
dat2
# [1] 3 2 1 1 1 2 3 1 2 2
Используя tidyverse и purr::imap_dfr, мы можем создать tibble со значениями и индексами рядом, arrange по значению и pull по индексам:
list_ <- list(c(3, 4, 5, 8), c(2, 6, 9, 10), c(1, 7))
library(tidyverse)
imap_dfr(list_,~tibble(.x,.y)) %>% arrange(.x) %>% pull(.y) %>% as.list
# [[1]]
# [1] 3
#
# [[2]]
# [1] 2
#
# [[3]]
# [1] 1
#
# [[4]]
# [1] 1
#
# [[5]]
# [1] 1
#
# [[6]]
# [1] 2
#
# [[7]]
# [1] 3
#
# [[8]]
# [1] 1
#
# [[9]]
# [1] 2
#
# [[10]]
# [1] 2
Менее красиво переведено в базе R (тот же вывод):
with(
as.data.frame(do.call(rbind,Map(cbind,a = list_, b =seq_along(list_)))),
as.list(b[order(a)]))
Приношу свои извинения, но я не могу понять, как получить
3 2 1 1 1 2 3 1 2 2из заданного ввода, по крайней мере, мне это не ясно. Спасибо