Не избыточная версия expand.grid
Функция R
expand.grid
возвращает всю возможную комбинацию между элементами поставляемых параметров. например.
> expand.grid(c("aa", "ab", "cc"), c("aa", "ab", "cc"))
Var1 Var2
1 aa aa
2 ab aa
3 cc aa
4 aa ab
5 ab ab
6 cc ab
7 aa cc
8 ab cc
9 cc cc
Знаете ли вы эффективный способ получить непосредственно (так без сравнения строк после expand.grid
) только "уникальные" комбинации между предоставленными векторами? Выход будет
Var1 Var2
1 aa aa
2 ab aa
3 cc aa
5 ab ab
6 cc ab
9 cc cc
EDIT комбинация каждого элемента с собой может быть в конечном итоге отброшена из ответа. Я действительно не нуждаюсь в ней в своей программе, хотя (математически) aa aa
будет одной (регулярной) уникальной комбинацией между одним элементом Var1
и другим из var2
.
Решение должно создавать пары элементов из обоих векторов (т.е. один из каждого входного вектора - так, чтобы он мог применяться к более чем двум входам)
Ответы
Ответ 1
Как насчет использования outer
? Но эта конкретная функция объединяет их в одну строку символов.
outer( c("aa", "ab", "cc"), c("aa", "ab", "cc") , "paste" )
# [,1] [,2] [,3]
#[1,] "aa aa" "aa ab" "aa cc"
#[2,] "ab aa" "ab ab" "ab cc"
#[3,] "cc aa" "cc ab" "cc cc"
Вы также можете использовать combn
для уникальных элементов двух векторов, если вам не нужны повторяющиеся элементы (например, aa aa
)
vals <- c( c("aa", "ab", "cc"), c("aa", "ab", "cc") )
vals <- unique( vals )
combn( vals , 2 )
# [,1] [,2] [,3]
#[1,] "aa" "aa" "ab"
#[2,] "ab" "cc" "cc"
Ответ 2
Если два вектора совпадают, в < <21 > есть функция combinations
:
library(gtools)
combinations(n = 3, r = 2, v = c("aa", "ab", "cc"), repeats.allowed = TRUE)
# [,1] [,2]
# [1,] "aa" "aa"
# [2,] "aa" "ab"
# [3,] "aa" "cc"
# [4,] "ab" "ab"
# [5,] "ab" "cc"
# [6,] "cc" "cc"
И без "aa" "aa"
и т.д.
combinations(n = 3, r = 2, v = c("aa", "ab", "cc"), repeats.allowed = FALSE)
Ответ 3
В базе R вы можете использовать это:
expand.grid.unique <- function(x, y, include.equals=FALSE)
{
x <- unique(x)
y <- unique(y)
g <- function(i)
{
z <- setdiff(y, x[seq_len(i-include.equals)])
if(length(z)) cbind(x[i], z, deparse.level=0)
}
do.call(rbind, lapply(seq_along(x), g))
}
Результаты:
> x <- c("aa", "ab", "cc")
> y <- c("aa", "ab", "cc")
> expand.grid.unique(x, y)
[,1] [,2]
[1,] "aa" "ab"
[2,] "aa" "cc"
[3,] "ab" "cc"
> expand.grid.unique(x, y, include.equals=TRUE)
[,1] [,2]
[1,] "aa" "aa"
[2,] "aa" "ab"
[3,] "aa" "cc"
[4,] "ab" "ab"
[5,] "ab" "cc"
[6,] "cc" "cc"
Ответ 4
В предыдущих ответах отсутствовал способ получить конкретный результат, а именно сохранить собственные пары, но удалить их с разными порядками. Пакет gtools имеет две функции для этих целей: combinations
и permutations
. В соответствии с этим сайтом:
- Когда порядок не имеет значения, это комбинация.
- Когда порядок имеет значение, это перестановка.
В обоих случаях мы принимаем решение о допустимости повторений или нет, и, соответственно, обе функции имеют аргумент repeats.allowed
, что дает 4 комбинации (вкусно мета!). Стоит пережить каждый из них. Я упростил вектор для отдельных букв для удобства понимания.
Перестановки с повторением
Наиболее широкая опция - это позволить как отношениям, так и по-разному упорядоченным параметрам:
> permutations(n = 3, r = 2, repeats.allowed = T, v = c("a", "b", "c"))
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "a"
[5,] "b" "b"
[6,] "b" "c"
[7,] "c" "a"
[8,] "c" "b"
[9,] "c" "c"
что дает нам 9 вариантов. Это значение можно найти по простой формуле n^r
i.e 3^2=9
. Это декартово произведение /join для пользователей, знакомых с SQL.
Есть два способа ограничить это: 1) удалить самозависимости (запретить повторы) или 2) удалить по-разному упорядоченные параметры (т.е. комбинации).
Комбинации с повторениями
Если мы хотим удалить по-разному упорядоченные опции, мы используем:
> combinations(n = 3, r = 2, repeats.allowed = T, v = c("a", "b", "c"))
[,1] [,2]
[1,] "a" "a"
[2,] "a" "b"
[3,] "a" "c"
[4,] "b" "b"
[5,] "b" "c"
[6,] "c" "c"
который дает нам 6 вариантов. Формула для этого значения равна (r+n-1)!/(r!*(n-1)!)
i.e. (2+3-1)!/(2!*(3-1)!)=4!/(2*2!)=24/4=6
.
Перестановки без повторения
Если вместо этого мы хотим запретить повторы, мы используем:
> permutations(n = 3, r = 2, repeats.allowed = F, v = c("a", "b", "c"))
[,1] [,2]
[1,] "a" "b"
[2,] "a" "c"
[3,] "b" "a"
[4,] "b" "c"
[5,] "c" "a"
[6,] "c" "b"
который также дает нам 6 вариантов, но разные! Количество опций такое же, как и выше, но это совпадение. Значение можно найти по формуле n!/(n-r)!
i.e. (3*2*1)/(3-2)!=6/1!=6
.
Комбинации без повторений
Наиболее ограничивающим является то, что мы не нуждаемся ни в корреляциях/повторениях, ни в по-разному упорядоченных вариантах, и в этом случае мы используем:
> combinations(n = 3, r = 2, repeats.allowed = F, v = c("a", "b", "c"))
[,1] [,2]
[1,] "a" "b"
[2,] "a" "c"
[3,] "b" "c"
который дает нам только 3 варианта. Количество опций может быть вычислено из довольно сложной формулы n!/(r!(n-r)!)
i.e. 3*2*1/(2*1*(3-2)!)=6/(2*1!)=6/2=3
.
Ответ 5
Try:
factors <- c("a", "b", "c")
all.combos <- t(combn(factors,2))
[,1] [,2]
[1,] "a" "b"
[2,] "a" "c"
[3,] "b" "c"
Это не будет включать в себя дубликаты каждого фактора (например, "a" "a" ), но вы можете легко добавлять их при необходимости.
dup.combos <- cbind(factors,factors)
factors factors
[1,] "a" "a"
[2,] "b" "b"
[3,] "c" "c"
all.combos <- rbind(all.combos,dup.combos)
factors factors
[1,] "a" "b"
[2,] "a" "c"
[3,] "b" "c"
[4,] "a" "a"
[5,] "b" "b"
[6,] "c" "c"