Возврат функции из списка из функции - PullRequest
1 голос
/ 21 февраля 2011

Я искал этот вопрос, но нашел ответы, которые не были достаточно конкретными.

Я очищаю старый код и пытаюсь убедиться, что следующее относительно чисто, и надеюсь, чтопозже он меня не укусит.

Мой вопрос касается передачи функции через функцию.Посмотрите на часть "y" следующего утверждения заговора.goo(df)[[1]](x) вещь работает, но я спрашиваю о неприятностях в любом случае?Если так, есть ли более чистый путь?

Кроме того, если функция goo() вызывается много-много раз, например, при анализе по методу Монте-Карло, это приведет к загрузке внутренних компонентов R или, возможно, вызовет какие-то проблемы со средой?

Редактировать(21.02.2011) --- Следующий код является лишь примером.Реальная функция "goo" имеет много кода, прежде чем она перейдет к оператору приблизительноfun ().

Ответы [ 3 ]

4 голосов
/ 21 февраля 2011

Трудно дать вам конкретные рекомендации, не зная точно, какой у вас код, но вот несколько вещей, на которые стоит обратить внимание:

  1. Действительно ли необходимо включать части ввода gooданные в его возвращаемом значении?Другими словами, можете ли вы сделать goo простой фабрикой, которая просто возвращает функцию?В вашем примере, по крайней мере, функция plot уже имеет все данные, необходимые для определения пределов.
  2. Если это невозможно, оставайтесь с этим шаблоном, но присвойте элементам gooвозвращают значения описательных имен, так что, по крайней мере, легко увидеть, что происходит, когда вы ссылаетесь на них.(Например, goo(df)$approx(x).) Если эта структура широко используется в вашем коде, рассмотрите возможность сделать ее классом S3.
  3. Наконец, не вызывайте goo(df) несколько раз в функции plot, просто чтобы получитьразные элементы.Когда вы делаете это, вы буквально каждый раз вызываете goo, что, как вы сказали, выполнит много кода.Кроме того, каждый вызов будет иметь свою собственную среду с копией входных данных (хотя R будет достаточно умным, чтобы уменьшить копирование до определенной степени и использовать тот же физический экземпляр df.) Вместо этого вызовите goo один раз, присвойте ее значение переменной и впоследствии обратитесь к этой переменной.
3 голосов
/ 21 февраля 2011

Я бы удалил уровень обработки функций и не использовал бы входные данные для генерации функций. Тогда вы можете не использовать свою функцию и вызывать приблизительно один раз.

Он также обобщает на входной фрейм данных любого размера, а не только один с 5 строками.

#Build a dataframe
df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))

#Build a function
fun <- approxfun(x = df$a, y = df$b, yright=max(df$b), method="linear", f = 1)

#Set up the plot range
x <- seq(1, 4.3, 0.01)

#Plot the function
plot(x, fun(x), type="l", xlim=c(0, max(df$a)), ylim=c(0, max(df$b)), lwd=2, col="red")

В конечном итоге это может быть не совсем то, что вам нужно, но это устраняет уровень сложности и дает более чистую отправную точку.

1 голос
/ 22 февраля 2011

Это может быть не лучше в большом моделировании по методу Монте-Карло, но для более простых ситуаций может быть более понятно включить диапазоны x и y в качестве атрибутов вывода из созданной функции, а не в список с созданной функцией.Таким образом, goo является более простой фабрикой, как упоминает Давор.Вы также можете сделать результат из своей функции объектом (в данном случае используя S3), чтобы его можно было отобразить более просто.

goo <- function(inp.df) {
  out.fun <- approxfun(x=inp.df$a, y=inp.df$b, yright=max(inp.df$b), 
                       method="linear", f=1)
  xmax <- inp.df$a[5]
  ymax <- inp.df$b[5]
  function(...) {
    structure(data.frame(x=x, y = out.fun(...)), 
              limits=list(x=xmax, y=ymax), 
              class=c("goo","data.frame"))
   }
}

plot.goo <- function(x, xlab="x", ylab="approx",  
                     xlim=c(0, attr(x, "limits")$x), 
                     ylim=c(0, attr(x, "limits")$y), 
                     lwd=2, col="red", ...) {
  plot(x$x, x$y, type="l", xlab=xlab, ylab=ylab, 
       xlim=xlim, ylim=ylim, lwd=lwd, col=col, ...)
}

Затем, чтобы сделать функцию для фрейма данных, вы должны сделать:

df <- data.frame(a=c(1, 2, 3, 4, 5), b=c(4, 3, 1, 2, 6))
goodf <- goo(df)

И чтобы использовать его на векторе, вы должны сделать:

x <- seq(1, 4.3, 0.01) 
goodfx <- goodf(x)
plot(goodfx)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...