Переписать цикл for в качестве приложения, в котором нет набора предопределенных значений для цикла, кроме количества циклов - PullRequest
0 голосов
/ 07 января 2019

Я делаю небольшой скрипт, который с учетом начального значения вычислит некоторые дополнительные значения и сохранит их. Моя функция в настоящее время такова:

func1 <- function(n, p, val){
  vals <- c(val)
  for(i in (1:n)){
    newVal <- getNewVal(p, val = tail(vals,n=1))
    vals <- c(vals, newVal)
  }
  return(vals)
}

Учитывая, что на самом деле у меня нет списка заданных значений, и что я буду продолжать идти n раза от последнего сгенерированного значения, я не могу думать, как это можно превратить в apply (), сохраняя получение новое значение, сохраняя его в списке значений и затем вызывая его снова с последним элементом в значениях.

Возможно ли это?

Пример ввода:

func1(10, 0.5, 1)
output vals (1,4,5,3,7,2,4,9,8,6,2)

Редактировать: getNewVal (), учитывая число p и значение val, вычислит новое значение.

1 Ответ

0 голосов
/ 07 января 2019

Есть несколько способов сделать это (это поможет, если вы предоставите getNewVal)

1. С помощью Reduce

Ваша задача сводится к x_n+1 = f(x_n); x_0 = const. Это типичный вариант использования для reduce:

# Reduce
  func_Reduce <- function (n, p, val) Reduce(function (x,y) getNewVal(p = p, val = x), 
                                             x = 1:n, init = val, accumulate = TRUE)

2. Использование семейства применения

Вот решение с использованием vapply из семейства применения

# Apply
  func_vapply <- function (n, p, val) vapply(0:n,
    function(i, p, val){
      if (i == 0) {
        vals <<- val # overwrites in the func. env.
        return (val)
      }
      newVal <- getNewVal(p, val = vals[length(vals)])
      vals <<- c(vals, newVal) # overwrites in the func. env.
      return(newVal)
    }, numeric(1), p = p, val = val)

Здесь нужно использовать <<-, чтобы отслеживать последний элемент vals.


3. Использование рекурсии

Эту задачу также можно выполнить с помощью рекурсии

# Recursion  
func_recursive <- function(n, p, val){
  if (n == 0) return (val)
  vals <- func_recursive (n-1, p, val)
  newVal <- getNewVal(p, val = vals[length(vals)])
  c(vals, newVal)
}

Хотя рекурсии следует использовать с определенной осторожностью.


Примеры

Вот пример:

# Dummy function
getNewVal <- function (p, val) val %/% p  
# Arguments
n <- 17
p <- 3
val <- 45459748

# Examples
func_Reduce(n = n, p = p, val = val)
func_vapply(n = n, p = p, val = val)
func_recursive(n = n, p = p, val = val)
# all yielding
# [1] 45459748 15153249  5051083  1683694   561231   187077    62359    20786     6928     2309      769      256       85       28        9        3        1        0

# benchmarking
microbenchmark::microbenchmark(func_Reduce(n = n, p = p, val = val),
                               func_vapply(n = n, p = p, val = val),
                               func_recursive(n = n, p = p, val = val)
                               )  
# Unit: microseconds
#                                    expr    min     lq     mean median      uq    max neval cld
#    func_Reduce(n = n, p = p, val = val) 25.163 26.257 28.65292 26.986 27.3515 82.417   100  a 
#    func_vapply(n = n, p = p, val = val) 30.268 30.998 32.82484 31.363 32.4570 80.958   100   b
# func_recursive(n = n, p = p, val = val) 23.339 24.798 27.16511 25.527 26.2570 82.417   100  a 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...