2013-05-31 69 views
1

我認爲R是在R中優化工作流程的一個常見問題。具體來說,我該如何避免出現文件夾已滿輸出的常見問題(繪圖,RData文件,csv等),過了一段時間後,他們是否知道他們來自哪裏或他們是如何生產的?部分地,它肯定涉及試圖對文件夾結構進行智能化。我一直在環顧四周,但我不確定最好的策略是什麼。到目前爲止,我已經用一種相當簡單的(矯枉過正的)方式解決了這個問題:我創建了一個函數metainfo(見下文),它用一個給定的文件名寫入帶有元數據的文本文件。這個想法是,如果產生了一個圖,就會發出這個命令來產生一個文件名與文件名完全相同的文本文件(當然,擴展名除外),其中包含關於系統,會話,軟件包的信息,R版本,功能和文件元數據功能被稱爲等等。問題是:R:改進工作流程並跟蹤輸出

(i)人們如何處理這個普遍問題?是否有明顯的方法可以避免我提到的問題? (ii)如果沒有,有沒有人有任何提示改善此功能?目前它可能很笨重,並不理想。特別是,從中獲得繪圖的文件名不一定有效(我使用的解決方案是由@hadley在1中提供的解決方案)。任何想法都會受到歡迎!

該函數假設爲git,所以請忽略產生的可能警告。這是主要的功能,存儲在一個文件metainfo.R

MetaInfo <- function(message=NULL, filename) 
{ 
    # message - character string - Any message to be written into the information 
    #   file (e.g., data used). 
    # filename - character string - the name of the txt file (including relative 
    #   path). Should be the same as the output file it describes (RData, 
    #   csv, pdf). 
    # 

    if (is.null(filename)) 
    { 
    stop('Provide an output filename - parameter filename.') 
    } 

    filename <- paste(filename, '.txt', sep='') 

    # Try to get as close as possible to getting the file name from which the 
    # function is called. 
    source.file <- lapply(sys.frames(), function(x) x$ofile) 
    source.file <- Filter(Negate(is.null), source.file) 
    t.sf <- try(source.file <- basename(source.file[[length(source.file)]]), 
       silent=TRUE) 

    if (class(t.sf) == 'try-error') 
    { 
    source.file <- NULL 
    } 

    func <- deparse(sys.call(-1)) 

    # MetaInfo isn't always called from within another function, so func could 
    # return as NULL or as general environment. 
    if (any(grepl('eval', func, ignore.case=TRUE))) 
    { 
    func <- NULL 
    } 

    time <- strftime(Sys.time(), "%Y/%m/%d %H:%M:%S") 
    git.h <- system('git log --pretty=format:"%h" -n 1', intern=TRUE) 
    meta <- list(Message=message, 
       Source=paste(source.file, ' on ', time, sep=''), 
       Functions=func, 
       System=Sys.info(), 
       Session=sessionInfo(), 
       Git.hash=git.h) 
    sink(file=filename) 
    print(meta) 
    sink(file=NULL) 
} 

然後可以在另一個函數被調用,存儲在另一個文件中,例如:

source('metainfo.R') 

RandomPlot <- function(x, y) 
{ 
    fn <- 'random_plot' 
    pdf(file=paste(fn, '.pdf', sep='')) 
    plot(x, y) 
    MetaInfo(message=NULL, filename=fn) 
    dev.off() 
} 

x <- 1:10 
y <- runif(10) 

RandomPlot(x, y) 

這種方式,用一個文本文件製作與劇情相同的文件名,並提供可能有助於弄清劇情製作的方式和位置的信息。

+0

我還應該補充說Makefiles很可能是解決方案的一部分。但是,它們並不總是可行的,因爲某些分析可能需要一些「手動」步驟,以至於無法按順序運行R文件。 – tcam

+0

由於您正在考慮Make,我在Drake中添加了對我的回答的參考。 –

+0

感謝您的建議!德雷克看起來很有趣。仍然試圖讓我的頭靠近它。除了最基本的形式之外,我並不特別習慣於製作。我一直在努力的部分是,Make有一個明確的分析,並且有一個Makefile來從頭到尾運行整個分析。問題是在進入這個階段之前,在探索性分析中,Make看起來不太合適。但它也許會促使您儘可能使分析儘可能重現,從而引發良好的實踐。 – tcam

回答

1

就一般R組織而言:我喜歡有一個腳本來重新創建項目的所有工作。任何項目都應該可以通過單擊進行重現,包括與該項目相關的所有圖表或論文。

所以,保持組織結構:保持不同的目錄中爲每個項目,每個項目都有自己的functions.R腳本來存儲與項目相關的非封裝功能,而且每個項目都有開始像

主腳本
## myproject 
source("functions.R") 
source("read-data.R") 
source("clean-data.R") 

等...一路通過。這應該有助於保持組織的一切,如果你得到新的數據,你只需要去早期的腳本來修復標題或任何其他內容,並通過一次點擊重新運行整個項目。

+0

這是真的,理想情況下它會如此簡單。但通常,在你進行簡明而清晰的分析之前,你會有一個更加開放的階段,在這個階段你會得到幾個R文件,大量的情節。一旦你有簡明的輸出,你可能會刪除這種階段,但如果你不這樣做,並且以後再回來,那麼可能很難找到解決方法。 – tcam

2

有一個名爲Project Template的軟件包,可幫助用R腳本,數據文件,圖表等組織和自動化典型工作流程。還有一些有用的文檔,如Workflow of statistical data analysis by Oliver Kirchkamp

如果您使用Emacs和ESS進行分析,則必須學習Org-Mode。我用它來組織我所有的工作。以下是它如何與R整合:R Source Code Blocks in Org Mode

還有一個名爲Drake的新免費工具,被稱爲「make for data」。

+0

感謝您的提示!我會檢查一下Project Template,但是當我發現它時,我將它理解爲更多地處理項目的基本設置(文件夾佈局等),但也許它已經超越了這個範圍!至於ESS,唉我用vi。也許有一個vi相當於...我會看看。 – tcam

1

我認爲我的問題隱藏了一定程度的混淆。環顧四周,並探索了迄今爲止提供的建議,我得出結論認爲,瞭解文件的製作地點和方式可能並不重要。實際上,您應該能夠清除任何輸出,並通過重新運行代碼進行重現。所以雖然我仍然可以使用上述功能獲取額外的信息,但實際上這是一個無情的問題,並且確實會時不時清理文件夾。這些想法更加雄辯地解釋了here。這當然不排除使用Make/Drake或Project Template,我會嘗試使用它。再次感謝@noah和@alex的建議!

0

現在還有一個R package called drake(製造R的數據框),獨立於Factual的Drake。 R包也是一個Make-like構建系統,它將代碼/依賴與輸出鏈接起來。

install.packages("drake") # It is on CRAN. 
library(drake) 
load_basic_example() 
plot_graph(my_plan) 
make(my_plan) 

喜歡它的前身remake,它有額外的獎勵,你不必跟蹤文件的麻煩一堆。 R中生成的對象在make()期間被緩存,並且可以輕鬆地重新加載。

readd(summ_regression1_small) # Read objects from the cache. 
loadd(small, large) # Load objects into your R session. 
print(small) 

但是你仍然可以使用文件作爲單引號目標。 (請參見基本示例中的'report.Rmd''report.md'my_plan。)