Re: [問題] 不會傳遞 expression 到sub-function

看板R_Language作者 (刃之56)時間11年前 (2013/06/03 03:00), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串8/8 (看更多)
剛剛又試了另一種寫法也成功了 ###################################################################### library('doBy') sdSubsetFun = function(group, dVar, data) { subf = substitute( (dVar > (mean(dVar) - 1*sd(dVar))) & (dVar < (mean(dVar) + 1*sd(dVar)))) do.call('subsetBy', list(group, subf, data)) } # Create Data x = rep(c('a','b','c'), 50) y = 1:150 tData = data.frame(aa = x, bb = y) subData = sdSubsetFun(~aa, bb, tData) ###################################################################### 雖然結果一樣,但是這應該跟我上一篇的 variable mapping 有所不同。 上一篇是直接把所有變數的 expression 都 map 到裏面的subsetBy 但是這一篇只有 dVar 會是 map 到外面的 expression group 和 data 就沒有被 map 成外面的 ~aa 和 tData 連我自己都覺得講的好繞口... ※ 引述《cog5566 (刃之56)》之銘言: : 感謝版主的回應。 : 我也是在看 github : 在經過 4個小時看完這篇內容之後, : https://github.com/hadley/devtools/wiki/Computing-on-the-language : 我終於成功弄(湊)出來了。好感動 : ###################################################################### : library('doBy') : sdSubsetFun = function(group, dVar, data) { : dataOut = substitute( : subsetBy(group, : (dVar > (mean(dVar) - 1*sd(dVar))) & : (dVar < (mean(dVar) + 1*sd(dVar))), : data = data) : ) : eval(dataOut) : } : # Create Data : x = rep(c('a','b','c'), 50) : y = 1:150 : tData = data.frame(aa = x, bb = y) : subData = sdSubsetFun(~aa, bb, tData) : ###################################################################### : 重點是要用 substitute 包住全部的 code : 而 substitute 很奧妙,它會替換裏面的 variable name 去對應 : 可能的值,然後輸出 language object : 有趣的是如果吧 substitute() 改成 quote() : 就不會替換成值。我也是現在才終於知道這兩個關鍵性的差別。 : ※ 引述《Wush978 (拒看低質媒體)》之銘言: : : 以下是我最初推文時測的code : : ```r : : library('doBy') : : sdSubsetFun = function(group, dVar, data) { : : sdVar = substitute(dVar) : : # 2SD threshold : : subsetThreshold <- substitute( (sdVar > (mean(sdVar) - 2*sd(sdVar))) & : : (sdVar < (mean(sdVar) + 2*sd(sdVar))) ) : : data$temp <- eval(subsetThreshold) : : dataOut = subsetBy(group, : : subset = temp, : : data = data) : : } : : # Create Data : : aa = rep(c('a','b','c'), 50) : : bb = 1:150 : : tData = data.frame(aa,bb) : : subData = sdSubsetFun(~aa, bb, tData) : : ``` : : 不過應該和Chris7462的修改類似。 : 是類似,但還是不一樣。Chris7462 一直試圖在 function 外弄出多餘的變數, : 來讓他的程式假性的沒有出錯。 : 在後來的回文我改了一個地方讓變數不會造成混肴 : x = rep(c('a','b','c'), 50) : y = 1:150 : tData = data.frame(aa = x, bb=y) : subData = sdSubsetFun(~aa, bb, tData) : 版主的程式會 work 是因為它在這一行 : data$temp <- eval(subsetThreshold) : eval 會去 evaluate bb這個變數。 : 但是其實 fuction 內沒有 bb 這個變數的,所以 R 會去外面抓 bb : (這點我也是很不習慣這種 scoping 的方式) : 剛好外面有 bb 所以看起來沒有出問題。 : 但是其實這個寫法出來的答案會是錯的,因為這時候 sd 是由 1:150來算的, : 因為是抓 bb = 1:150 : 而不是依組別算的。 : 現在把function 外變數改成這樣x,y的話,就會出錯。因為fuction 外面其實沒有 bb : bb 是在 tData 裏面的變數,如果沒有 attach() 到 search path, : 是根本抓不到的。 : ====================================================================== : 總結來說,就是有沒有辦法設計一個 function 他是可以照組別刪去 : data frame 特定 variable 的 2sd 之外的資料呢? : 我希望在我有一個 data frame tData 的情況下, : sdSubsetFun 這個 function : sdSubsetFun = function(group, dVar, data) : 的 dVar 的引數輸入的時候,我可以直接放 data frame 的 variable name : 而不用利用 attach() 或是做出而外的變數來達成我的目標。 : 因為 subset, subsetBy 等等的也是這樣就可以做到 : 一個解答就是以上的 code : 我不知道有沒有更好的解法,如果有也請多指教。 : 我覺得 R 在這一部份可能跟 fucntional programming 有關的實在很複雜。 : : --- : : 關於物件的是屬於symbol或character,也就是後來cog5566提到關於`rm`函數行為的問題, : : 這也是我過去學R ,到目前覺得很不可思議和不方便的地方。 : : cog5566可以用以下的方式來探索函數的行為: : : ```r : : debug(rm) : : x <- "y" : : y <- 10 : : rm(x) : : ``` : : 這之後會進入除錯模式,你可以巨細靡遺的觀察`rm`函數的行為。 : : 你會發現有種叫作"name"型態的物件。 : : 也可以去追相關函數的說明文件,也許你就可以搞清楚了。 : : ps. 我最近事情有點多,就沒追下去搞懂他了。 : : 我也不太確定Hadley的R advanced裏面有沒有提到這件事情。 : : ps. 現在github好像掛了,晚點我再補連結。 : : 期待你搞清楚後也可以播空發篇文章教教我,先謝謝了。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 139.184.222.89
文章代碼(AID): #1HgvP0vF (R_Language)
討論串 (同標題文章)
文章代碼(AID): #1HgvP0vF (R_Language)