2015-12-02 88 views
2

在數學中,當組合函數時,可以使用普通算術運算(例如,在R中對函數進行算術運算的最佳方法是什麼?

u = 2*x 
v = log(x) 

,然後簡單地

f = u + v 

我做了很多,你必須構建複雜的數學運算的數值工作。能夠使用更像這樣的符號將是非常有幫助的。例如,R中它可能看起來像

f <- function.arithmetic('u+v', args=c('x')) 

對於一些非標準的評價,這甚至是簡單的

f(x) %def% u + v 

其中u和v已經定義x的函數。

是否有簡單的方法來設置此語法?例如,分解表達式並將u(x)和v(x)代入它們所在的位置 - 然後執行一個普通的eval。 (我會相信現有的解析功能比一些黑客工具,我寫了。我知道,「分析」並沒有這樣做。)已經建議將工作

答案,但他們不是寫

似乎更復雜
f <- function(x) u(x) + v(x) 

如果表達式更復雜,這個表示法開始變得越來越難以閱讀。我想要設置一些更簡單,更易讀,更接近上述數學符號的東西。

+2

如果你問「怎麼做這個R中的最佳途徑」,而不是你會得到更少的厭惡你的問題「做了包存在嗎?」 –

+1

可能會看到[** Ryacas **](https://cran.r-project.org/web/packages/Ryacas/index.html)包。例如'庫(Ryacas); u < - 表達式(2 * x); v < - 表達式(log(x)); yacas(表達式(U + V));簡化(yacas(表達式(U * U + V)));的eval(yacas(表達式(U + V))),列表(x = 44)'等 –

+0

(這一句應改爲'的eval(yacas(表達式(U + V)),列表(x = 44) )') –

回答

3

這裏有幾種方法:

1)Ops/Math這可以使用S3或S4完成。我們只說明S3。

Compose <- function(f, g) { 
    if (missing(g)) structure(f, class = c("functional", "function")) 
    else Compose(function(...) f(g(...))) 
} 

Ops.functional <- function(e1, e2) { 
    op <- match.fun(.Generic) 
    Compose(if (is.numeric(e1)) function(...) op(e1, e2(...)) 
      else if (is.numeric(e2)) function(...) op(e1(...), e2) 
      else function(...) op(e1(...), e2(...))) 
} 

Math.functional <- function(x, ...) { 
    op <- match.fun(.Generic) 
    Compose(op, x) 
} 

這裏有兩個例子:

u <- Compose(function(x) 2*x) 
v <- Compose(log) 

(u + v)(pi/2) # example 1 
## [1] 3.593175 

(exp(u*v)/(1 + u^2 + v^2)) (pi/2) # example 2 
## [1] 0.3731149 

注:u可能交替地被定義爲u <- 2 * Compose(identity)。事實上,我們可以定義:

Id <- Compose(identity) 
u <- 2*Id 
v <- log(Id) 

2)定義自己的函數這並不是真正意義上的工作。可能少於一頁來定義所有常用功能。這可以使用%...%infix操作符完成,但是如果您確實想要使用上面的中綴路由(1),那麼似乎更可取。所以採用這種方法我們保持簡單。可以增強以下內容以允許將數值參數視爲常量函數,就像我們在(1)中所做的那樣。

Plus <- function(f, g) function(...) f(...) + g(...) 

Plus(function(x) 2*x, log)(pi/2) 
## [1] 3.593175 
+0

方法1看起來非常接近,我在想什麼的 - 很優雅。我也應該通過實施來學到很多東西。 –

4

這是一箇中綴「+」的形式G.Grothendieck的答案投 - 運營商:

`%+%` <- function(f1, f2) { function(x) {f1(x) +f2(x)} } 

    f <- cos %+% sin 
f 
#----- 
function(x) {f1(x) +f2(x)} 
<environment: 0x7ffccd7eeea8> 
#------- 

f(0) 
#[1] 1 

也存在「funprog頁面需要被拉到了功能性成分的例子其中一個函數名稱,例如?Reduce。也可以被定義爲接受額外的參數:

`%+%` <- function(f1, f2) { function(x,...) {f1(x,...) +f2(x,...)} } 
f2 <- dt %+% dt 
#-- testing--- 
> f2(0) 
Error in f1(x, ...) : argument "df" is missing, with no default 
> f2(0, 6) 
[1] 0.7654655 
> dt(0,6) 
[1] 0.3827328 

要看到這是如何內部處理的,你可以通過檢查存儲與所產生的封閉環境恢復的定義:

> ls(envir=environment(f2)) 
[1] "f1" "f2" 
> environment(f2)$f1 
function (x, df, ncp, log = FALSE) 
{ 
    if (missing(ncp)) 
     .Call(C_dt, x, df, log) 
    else .Call(C_dnt, x, df, ncp, log) 
} 
<bytecode: 0x7ffcc63e8ff8> 
<environment: namespace:stats> 

的問題與你的榜樣你沒有以R功能的方式定義u和v。據推測,這不會是你提出的用例的情況。

> u = function(x,...)2*x 
> v = function(x,...) (log(x)) 
> f <- u %+% v 
> f(4) 
[1] 9.386294 

一些這種編程風格可以通過哈德利的lazyeval包支持:

> require(lazyeval) 
Loading required package: lazyeval 
> help(pac=lazyeval) 
> lazy_eval(interp(~ u + v, u = sum(1:10), v=sum(1:5))) 
[1] 70 
> x <- 1:10; y=1:5 
> lazy_eval(interp(~ u + v, u = sum(x), v=sum(y))) 
[1] 70 
> lazy_eval(interp(~ u/v, u = sum(x), v=sum(y))) 
[1] 3.666667 
> lazy_eval(interp(~ log(u)/v, u = sum(x), v=sum(y))) 
[1] 0.2671555 

但我遇到了一些困惑,我真的不能明白:

e2 <- ~ exp(u * v)/(1 + x)^2 
lazy_eval(interp(e2, u = sum(x)/100, v=sum(y)/100)) 
#[1] 0.271499668 0.120666519 0.067874917 0.043439947 0.030166630 0.022163238 0.016968729 
#[8] 0.013407391 0.010859987 0.008975196 

exp(sum(x)/100 +sum(y)/100)/(1+x)^2 
[1] 0.50343818 0.22375030 0.12585954 0.08055011 0.05593758 0.04109699 0.03146489 0.02486114 
[9] 0.02013753 0.01664258 
+0

我認爲,但它也需要爲師,求冪和乘法特殊infixed(危險!)我可能需要編寫代碼,例如(在僞代碼) lapply(參數, function.arithmetic(exp(u * v)/(1 + x)^ 2,x)) 等等 - 比我們通常使用的組合更容易閱讀。 –

+0

好像您應該超出請求的僞代碼級別並實際創建一些R對象來開始工作。無論是'u'還是'v'都沒有用無錯代碼定義。 –

相關問題