#r #combinations #combinatorics #cartesian-product
Вопрос:
Мне нужна функция, аналогичная expand.grid
, но без комбинаций повторяющихся элементов.
Вот упрощенная версия моей проблемы.
X1 = c("x","y","z")
X2 = c("A","B","C")
X3 = c("y","C","G")
d <- expand.grid(X1,X2,X3)
d
Var1 Var2 Var3
1 x A y
2 y A y
3 z A y
4 x B y
. . . .
. . . .
. . . .
23 y B G
24 z B G
25 x C G
26 y C G
27 z C G
d
имеет 27 рядов. Но 6 из них содержат повторяющиеся значения, которые мне не нужны.: 2, 5, 8, 16, 17 amp; 18
Есть ли способ получить остальные 21 строку, которые не содержат никаких дубликатов.
Обратите внимание, что векторы имеют более 3 элементов ( c("x","y","z","k","m"...)
до 50), а количество векторов в реальном случае превышает 3. ( X4
, X5
, X6
… до 11 ). Из-за этого расширенный объект становится очень большим, и оперативная память не может с ним справиться.
Комментарии:
1. Если я правильно об этом думаю, вы пытаетесь создать сетку, содержащую 50^11 или 4.882813 e 18 элементов. Я получил R, чтобы выдать мне сообщение об ошибке с 9 векторами длиной 50, в котором говорилось, что невозможно выделить вектор размером >7 ПБ. Так что не удивляйтесь, что это не укладывается в памяти. Есть ли другой способ решить эту проблему? Можете ли вы сказать нам, каков диапазон ваших фактических данных? Если существует очень высокая вероятность дубликатов в любой заданной строке, мы могли бы наращивать это постепенно. Но я не думаю, что это сработает, если не будет тонны дубликатов.
2. Не обращайте внимания на мой комментарий, используйте решение @joseph-wood
3. @ngwalton, ваш комментарий выше точен. Пожалуйста, не удаляйте его, так как это касается сути этой проблемы.
Ответ №1:
В RcppAlgos
* есть функция, comboGrid
которая выполняет эту функцию:
library(RcppAlgos) ## as of v2.4.3
comboGrid(X1, X2, X3, repetition = F)
# Var1 Var2 Var3
# [1,] "x" "A" "C"
# [2,] "x" "A" "G"
# [3,] "x" "A" "y"
# [4,] "x" "B" "C"
# [5,] "x" "B" "G"
# [6,] "x" "B" "y"
# [7,] "x" "C" "G"
# [8,] "x" "C" "y"
# [9,] "y" "A" "C"
# [10,] "y" "A" "G"
# [11,] "y" "B" "C"
# [12,] "y" "B" "G"
# [13,] "y" "C" "G"
# [14,] "z" "A" "C"
# [15,] "z" "A" "G"
# [16,] "z" "A" "y"
# [17,] "z" "B" "C"
# [18,] "z" "B" "G"
# [19,] "z" "B" "y"
# [20,] "z" "C" "G"
# [21,] "z" "C" "y"
Большой Тест
set.seed(42)
rnd_lst <- lapply(1:11, function(x) {
sort(sample(LETTERS, sample(26, 1)))
})
## Number of results that expand.grid would return if your machine
## had enough memory... over 300 trillion!!!
prettyNum(prod(lengths(rnd_lst)), big.mark = ",")
# [1] "365,634,846,720"
exp_grd_test <- expand.grid(rnd_lst)
# Error: vector memory exhausted (limit reached?)
system.time(cmb_grd_test <- comboGrid(rnd_lst, repetition=FALSE))
# user system elapsed
# 9.866 0.330 10.196
dim(cmb_grd_test)
# [1] 3036012 11
head(cmb_grd_test)
# Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10 Var11
# [1,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "K"
# [2,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "L"
# [3,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "M"
# [4,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "N"
# [5,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "O"
# [6,] "A" "E" "C" "B" "D" "G" "F" "H" "J" "I" "P"
* Я являюсь автором RcppAlgos
Комментарии:
1. Это сработало как заклинание. Спасибо тебе @Джозеф Вуд
Ответ №2:
(Извините, я только что понял, что ваша проблема в такой же степени связана с размером, поэтому удаление их после создания может оказаться невозможным. Для этого, возможно, это не лучший ответ, но я сохраню его для более мелких и связанных с этим вопросов.)
основание R
Я жестко закодировал «3», но вы можете использовать ncol(d)
и/или ncol(d)-1
для программного использования.
d[lengths(apply(d, 1, unique)) > 2, ]
# Var1 Var2 Var3
# 1 x A y
# 3 z A y
# 4 x B y
# 6 z B y
# 7 x C y
# 9 z C y
# 10 x A C
# 11 y A C
# 12 z A C
# 13 x B C
# 14 y B C
# 15 z B C
# 19 x A G
# 20 y A G
# 21 z A G
# 22 x B G
# 23 y B G
# 24 z B G
# 25 x C G
# 26 y C G
# 27 z C G
(Имена строк не сбрасываются, вы можете увидеть пробелы, чтобы убедиться, что это не 27 строк.)
И чтобы убедиться, вот строки с дураками:
d[lengths(apply(d, 1, unique)) < 3, ]
# Var1 Var2 Var3
# 2 y A y
# 5 y B y
# 8 y C y
# 16 x C C
# 17 y C C
# 18 z C C
Комментарии:
1. Я рад, что вы ответили, потому что я действительно думал о вашем
expand.grid
итераторе .2. Я давно не смотрел (и не использовал) это, спасибо, что напомнили мне! Да, это тоже может быть полезно здесь. В зависимости от того, как они намерены его использовать, это также может быть фактором … посмотрим, что думает @Ex-StrConsultant 🙂