R: Удалить повторяющиеся пары из входа в функцию vecotrized перед запуском функции - PullRequest
1 голос
/ 26 апреля 2020

Я написал код для поиска дружных пар . В настоящее время это очень неэффективно, и я пытаюсь решить свои проблемы. Как часть этого, у меня есть функция areAmicablePairs(a,b), которая делает именно то, что вы ожидаете, за исключением того, что она не может обрабатывать случаи, когда a или b равны 1.

. попробуйте найти каждую дружную пару для a и b под некоторым номером n, я пробежал which(outer(2:n,2:n,Vectorize(areAmicablePairs)),arr.ind = TRUE). Мне не потребовалось много времени, чтобы заметить очевидную неэффективность того, как вводятся данные для этой функции. В частности, есть повторение. Например, он проверит, являются ли 100 и 101 дружными парами, и позже проверит, равны ли 101 и 100, эквивалентному случаю.

Это дает мне мой вопрос, без сохранения списка в памяти или создания такого списка. и отфильтровывая его во время выполнения, оба из которых, я полагаю, очень неэффективны (я действительно не хочу хранить, скажем, список 20 000 на 20 000 в памяти), как я могу передать этой vecotrized функции список уникальных пар числа от 2 до п? Я мог бы сделать очень тщательно сконструированный для l oop, но существование таких функций, как apply, mapply и unique, заставляет меня надеяться, что есть лучший способ.

Пример: Предположим, что я использую это как заполнитель для areAmicablePairs:

areAmicablePairs<-function(a,b)
{
    return(a==b)
}

Затем я пытаюсь запустить which(outer(2:1000,2:1000,Vectorize(areAmicablePairs)),arr.ind = TRUE) без повторения эквивалентных входных данных, таких как a=5, b=2 и a=2, b=5.

Ответы [ 2 ]

3 голосов
/ 26 апреля 2020

Если нам нужно больше эффективности, тогда опция comboGeneral из RcppAlgos

library(RcppAlgos)
n <- 20
r <- 2
result2 <- comboGeneral(n, r)

-проверка

identical(resul2, gtool::combinations(n, r))
#[1] TRUE
2 голосов
/ 26 апреля 2020

Вы можете использовать combinations() из gtools для создания таких уникальных пар (перестановок с несоответствием порядка). Но это все равно создаст очень большую матрицу размера:

$\frac{n!}{r!(n-r)!}$.

library(gtools)

n <- 20
r <- 2
result <- combinations(n, r)

Другой вариант - повторить это поведение, просто более эффективно увеличивая две переменные. Вместо того, чтобы пробегать все числа 2:n для первой переменной и 2:n для второй, вы можете установить b <- a после увеличения a и проверки всех b:n

Вот некоторый псевдокод просто чтобы проиллюстрировать увеличение

a <- 2
b <- 2

testing_numbers <- function(a, b, lim){
  while (a < lim){
    while (b < lim){
      if (some_condition){
        paste(a, b, True)
      } else{
        b <- b + 1
      }
    }
    a <- a + 1
    b <- a
  }
}

Для вашей векторизованной функции это означает, что вы можете использовать что-то вроде этого:

while (a < lim){
  # vector of the numbers still to test
  b_vec <- a:lim
  # repeat vector of the first number in the pair
  a_rep <- rep(a, times=length(b_vec))
  # apply function to both of these vectors
  mapply(your_test, b_vec, a_rep)
  a <- a + 1
}
...