Фильтрация числового вектора в R (против Python в виде списка) - PullRequest
0 голосов
/ 03 августа 2020

Пытаюсь узнать про R; Я писал функцию для возврата (правильных) делителей числа. В Python я могу использовать метод фильтрации, например:

def divisors(n):
    numbers = list(range(1,n))
    an_iterator = filter(lambda x: n % x ==0, numbers)
    return(list(an_iterator))

Какой хороший способ написать такую ​​функцию, на этот раз работая с вектором в R? Пока у меня есть это:

divisors <- function(n){
  vec <- 1:(n-1)
  vec <- ifelse(n %% vec == 0, vec, FALSE)
  vec <- vec[vec!=FALSE]
  return(vec)
}

РЕДАКТИРОВАТЬ: Я также нашел снизу функцию «which ()»:

divisors <- function(n) {
  vec <- 1:(n-1)
  vec <- vec[which(n %% vec == 0)]
  return(vec)
}

Ответы [ 2 ]

2 голосов
/ 03 августа 2020

Я думаю, что лучший способ - воспользоваться подходом R vector , который можно рассматривать как очень эффективный для l oop. Например:

divisors = function (n) {
  div = 1:(n - 1)
  div[n %% div == 0]
}

(примечание: я использую оператор = для назначения, это не обычная практика в R, где <- гораздо более распространен. Я использую его здесь, потому что похож на способ выполнения присваиваний на других языках, включая Python)

Здесь div = 1:(1 - n) создаст вектор возможных делителей. n %% div вернет остаток для n / div в виде вектора той же длины, что и div. Это как если бы мы сделали для l oop ранжирование через каждый элемент div и конкатенацию каждого результата. Это то, что люди называют векторизацией в R, этот процесс написан на C и действительно эффективен. Последний бит - это подмножество (фильтр) div, чтобы получить только правильные делители. Я снова использую здесь подход vector , генерируя логический вектор с помощью n %% div == 0. Подмножество с этим вернет только те значения из div, для которых выполняется условие, поэтому

> divisors(26)
[1]  1  2 13

Best,

1 голос
/ 03 августа 2020

Многие функции в R по умолчанию очень хорошо работают с векторами, поэтому, например, если вы оцените 6 %% 1:6, вы получите 0 0 0 2 1 0. Все 0 означают, что 6 были равномерно разделены. Поскольку вам нужны фактические числа, которые делятся поровну, а не результат, вы хотите сравнить результаты с 0 или спросить 0 0 0 2 1 0 == 0, который вернет TRUE TRUE TRUE FALSE FALSE TRUE. С этим результатом вы можете проиндексировать исходный вектор, чтобы вернуть правильное подмножество (1:6)[(6 %% 1:6) == 0], однако, поскольку сами индексы указывают правильное подмножество, в нашем случае я использовал функцию R which, которая возвращает индексы для TRUE значений в векторе.

Также, чтобы найти правильные делители, вам нужно всего go до половины значения, которое вы исследуете. Функция floor гарантирует, что результат будет целым числом для нечетных чисел.

divisors <- function(n) {
    which((n %% 1:floor(n / 2)) == 0)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...