IT story

큰 R 프로그램을 구성하는 방법?

hot-time 2020. 6. 5. 08:22
반응형

큰 R 프로그램을 구성하는 방법?


복잡한 R 프로젝트를 수행하면 스크립트가 길고 혼란스러워집니다.

내 코드가 항상 즐겁게 사용할 수 있도록 채택 할 수있는 몇 가지 방법은 무엇입니까? 나는 같은 것들에 대해 생각하고있다

  • 소스 파일에 함수 배치
  • 다른 소스 파일로 무언가를 나눌 때
  • 마스터 파일에 있어야 할 것
  • 기능을 조직 단위로 사용 (R이 전역 상태에 액세스하기 어려운 경우 가치가 있는지 여부)
  • 들여 쓰기 / 줄 바꿈 관행.
    • 치료 ({?
    • 1) 또는 2 줄에)} 같은 것을 넣습니까?

기본적으로 큰 R 스크립트를 구성하기위한 규칙은 무엇입니까?


표준 답변은 패키지를 사용 하는 것입니다. 웹에서 다른 자습서는 물론 Writing R Extensions 설명서를 참조하십시오 .

그것은 당신에게 제공

  • 주제별로 코드를 구성하는 준 자동 방법
  • 도움말 파일을 작성하여 인터페이스에 대해 생각할 것을 강력히 권장합니다.
  • 통해 많은 위생 검사 R CMD check
  • 회귀 테스트를 추가 할 수있는 기회
  • 네임 스페이스를위한 수단뿐만 아니라

source()코드를 실행 하면 실제로 짧은 스 니펫에 효과적입니다. 내부 리포지토리의 내부 패키지를 작성할 수 있으므로 게시 할 계획이없는 경우에도 패키지의 모든 내용이 패키지에 있어야합니다.

'편집 방법'부분에 대해서는 R Internals 매뉴얼 에 섹션 6의 우수한 R 코딩 표준 이 있습니다. 그렇지 않으면 Emacs의 ESS 모드 에서 기본값을 사용하는 경향이 있습니다 .

2008-Aug-13 업데이트 : David Smith가 Google R 스타일 가이드에 대해 블로그에 올렸습니다 .


나는 다른 기능을 자신의 파일에 넣는 것을 좋아합니다.

그러나 나는 R의 패키지 시스템을 좋아하지 않는다. 사용하기가 다소 어렵습니다.

파일 기능을 환경 내에 배치하고 (다른 모든 언어가 "네임 스페이스"라고 부르는) 대체 파일을 선호합니다. 예를 들어, 'util'기능 그룹을 다음과 같이 만들었습니다.

util = new.env()

util$bgrep = function [...]

util$timeit = function [...]

while("util" %in% search())
  detach("util")
attach(util)

이것은 모두 util.R 파일에 있습니다 . 당신이 그것을 소싱 할 때, 당신은 호출 할 수있는 환경 '유틸리티'를 얻습니다 util$bgrep(). 더 나아가서, 그 attach()부름은 그렇게 정당 bgrep()하고 그러한 일을 직접적으로 만듭니다. 이러한 함수를 모두 자체 환경에 두지 않은 경우 통역사의 최상위 네임 스페이스 (표시되는 네임 스페이스)를 오염시킵니다 ls().

모든 파일이 모듈 인 Python의 시스템을 시뮬레이션하려고했습니다. 그것은 더 나을 것이지만 이것은 괜찮은 것 같습니다.


프로그래머라면 특히 분명하게 들릴지 모르지만, 논리적이고 물리적 인 코드 단위에 대한 생각은 다음과 같습니다.

이것이 귀하의 경우인지 모르겠지만 R에서 일할 때 큰 복잡한 프로그램을 염두에 두지 않습니다. 나는 보통 하나의 스크립트로 시작하고 코드를 논리적으로 분리 가능한 단위로 분리하며 종종 함수를 사용합니다. 데이터 조작 및 시각화 코드는 자체 기능 등에 배치됩니다. 이러한 기능은 파일의 한 섹션 (그룹의 데이터 조작, 시각화 등)으로 그룹화됩니다. 궁극적으로 스크립트를보다 쉽게 ​​유지 관리하고 결함 비율을 낮추는 방법에 대해 생각하고 싶습니다.

미세하고 거칠게 기능을 만드는 방법은 다양하고 다양한 규칙이 있습니다. 예를 들어 15 줄의 코드 또는 "이름으로 식별되는 하나의 작업을 수행해야하는 기능"등. 마일리지는 다양합니다. . R은 참조 별 호출을 지원하지 않기 때문에 일반적으로 데이터 프레임이나 유사한 구조를 전달할 때 함수를 너무 세분화하는 방법이 다양합니다. 그러나 이것이 R을 처음 시작할 때 바보 같은 성능 오류에 대한 과도한 보상 일 수 있습니다.

논리 단위를 자체 물리 단위 (예 : 소스 파일 및 패키지와 같은 더 큰 그룹화)로 추출 할 때는 언제입니까? 두 가지 경우가 있습니다. 첫째, 파일이 너무 커지고 논리적으로 관련이없는 단위 사이를 스크롤하면 성가신 일입니다. 둘째, 다른 프로그램에서 재사용 할 수있는 기능이 있다면. 일반적으로 데이터 조작 기능과 같은 그룹화 된 단위를 별도의 파일에 배치하여 시작합니다. 그런 다음 다른 스크립트에서이 파일을 제공 할 수 있습니다.

함수를 배포하려면 패키지에 대한 생각을 시작해야합니다. 프로덕션에 R 코드를 배포하거나 다양한 이유로 다른 사람들이 재사용하기 위해 배포하지 않습니다. 또한 소스 파일 모음을 지속적으로 수정하고 추가하는 경향이 있으며 변경을 할 때 패키지를 다루지 않습니다. 따라서이 부분에 대한 자세한 내용은 Dirk와 같은 다른 패키지 관련 답변을 확인해야합니다.

마지막으로, 귀하의 질문이 R에만 국한되는 것은 아니라고 생각합니다. Steve McConnell의 Code Complete를 읽고 그러한 문제와 코딩 방법에 대한 많은 지혜가 담긴 코드를 읽는 것이 좋습니다.


I agree with Dirk advice! IMHO, organizing your programs from simple scripts to documented packages is, for Programming in R, like switching from Word to TeX/LaTeX for writing. I recommend to take a look at the very useful Creating R Packages: A Tutorial by Friedrich Leisch.


My concise answer:

  1. Write your functions carefully, identifying general enough outputs and inputs;
  2. Limit the use of global variables;
  3. Use S3 objects and, where appropriate, S4 objects;
  4. Put the functions in packages, especially when your functions are calling C/Fortran.

I believe R is more and more used in production, so the need for reusable code is greater than before. I find the interpreter much more robust than before. There is no doubt that R is 100-300x slower than C, but usually the bottleneck is concentrated around a few lines of code, which can be delegated to C/C++. I think it would be a mistake to delegate the strengths of R in data manipulation and statistical analysis to another language. In these instances, the performance penalty is low, and in any case well worth the savings in development effort. If execution time alone were the matter, we'd be all writing assembler.


I've been meaning to figure out how to write packages but haven't invested the time. For each of my mini-projects I keep all of my low-level functions in a folder called 'functions/', and source them into a separate namespace that I explicitly create.

The following lines of code will create an environment named "myfuncs" on the search path if it doesn't already exist (using attach), and populate it with the functions contained in the .r files in my 'functions/' directory (using sys.source). I usually put these lines at the top of my main script meant for the "user interface" from which high-level functions (invoking the low-level functions) are called.

if( length(grep("^myfuncs$",search()))==0 )
  attach("myfuncs",pos=2)
for( f in list.files("functions","\\.r$",full=TRUE) )
  sys.source(f,pos.to.env(grep("^myfuncs$",search())))

When you make changes you can always re-source it with the same lines, or use something like

evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))

to evaluate additions/modifications in the environment you created.

It's kludgey I know, but avoids having to be too formal about it (but if you get the chance I do encourage the package system - hopefully I will migrate that way in the future).

As for coding conventions, this is the only thing I've seen regarding aesthetics (I like them and loosely follow but I don't use too many curly braces in R):

http://www1.maths.lth.se/help/R/RCC/

There are other "conventions" regarding the use of [,drop=FALSE] and <- as the assignment operator suggested in various presentations (usually keynote) at the useR! conferences, but I don't think any of these are strict (though the [,drop=FALSE] is useful for programs in which you are not sure of the input you expect).


Count me as another person in favor of packages. I'll admit to being pretty poor on writing man pages and vignettes until if/when I have to (ie being released), but it makes for a real handy way to bundle source doe. Plus, if you get serious about maintaining your code, the points that Dirk brings up all come into plya.


I also agree. Use the package.skeleton() function to get started. Even if you think your code may never be run again, it may help motivate you to create more general code that could save you time later.

As for accessing the global environment, that is easy with the <<- operator, though it is discouraged.


Having not learned how to write packages yet, I have always organized by sourcing sub scripts. Its similar to writing classes but not as involved. Its not programatically elegant but I find I build up analyses over time. Once I have a big section that works I often move it to a different script and just source it since it will use the workspace objects. Perhaps I need to import data from several sources, sort all of them and find the intersections. I might put that section into an additional script. However, if you want to distribute your "application" for other people, or it uses some interactive input, a package is probably a good route. As a researcher I rarely need to distribute my analysis code but I OFTEN need to augment or tweak it.


I have been also searching for the holy grail of the right workflow for putting together an R large project. I found last year this package called rsuite, and, certainly, it was what I looking for. This R package was explicitly developed for deployment of large R projects but I found that it can be used for smaller, medium size, and large size R projects. I will give links to real world examples in a minute (below), but first I want to explain the new paradigm of building R projects with rsuite.

Note. I am not the creator or developer of rsuite.

  1. We have been doing projects all wrong with RStudio; the goal shouldn't be the creation of a project or a package but of a larger scope. In rsuite you create a super-project or master project, which holds the standard R projects and R packages, in all combinations possible.

  2. By having an R super-project you don't need anymore Unix make to manage the lower levels of the R projects underneath; you use R scripts at the top. Let me show you. When you create a rsuite master project, you get this folder structure:

enter image description here

  1. The folder R is where you put your project management scripts, the ones that will replace make.

  2. The folder packages is the folder where rsuite holds all the packages that compose the super-project. You can also copy paste a package that is not accessible from the internet, and rsuite will build it as well.

  3. the folder deployment is where rsuite will write all the package binaries that were indicated in the packages DESCRIPTION files. So, this makes, by itself, you project totally reproducible accros time.

  4. rsuite comes with a client for all operating systems. I have tested them all. But you can also install it as an addin for RStudio.

  5. rsuite also lets you build an isolated conda installation in its own folder conda. This is not an environment but a physical Python installation derived from Anaconda in your machine. This works together with R's SystemRequirements, from which you could install all the Python packages you want, from any conda channel you want.

  6. You can also create local repositories to pull R packages when you are offline, or want to build the whole thing faster.

  7. If you want, you can also build the R project as a zip file and share it with colleagues. It will run, providing your colleagues have the same R version installed.

  8. Another option is building a container of the whole project in Ubuntu, Debian, or CentOS. So, instead of sharing a zip file with your project build, you share the whole Docker container with your project ready to run.

I have been experimenting a lot with rsuite looking for full reproducibility, and avoid depending of the packages that one installs in the global environment. This is wrong because as soon as you install a package update, the project, more often than not, stops working, specially those packages with very specific calls to a function with certain parameters.

The first thing I started to experiment was with bookdown ebooks. I have never been lucky enough to have a bookdown to survive the test of time longer than six months. So, what I did is converting the original bookdown project to follow the rsuite framework. Now, I don't have to worry about updating my global R environment, because the project has its own set of packages in the deployment folder.

The next thing I did was creating machine learning projects but in the rsuite way. A master, orchestrating project at the top, and all sub-projects and packages to be under the control of the master. It really changes the way you code with R, making you more productive.

After that I started working in a new package of mine called rTorch. This was possible, in large part, because of rsuite; it lets you think and go big.

One piece of advice though. Learning rsuite is not easy. Because it presents a new way of creating R projects, it feels hard. Do not dismay at the first attempts, continue climbing the slope until you make it. It requires advanced knowledge of your operating system and of your file system.

I expect that one day RStudio allows us to generate orchestrating projects like rsuite does from the menu. It would be awesome.

Links:

RSuite GitHUb repo

r4ds bookdown

keras and shiny tutorial

moderndive-book-rsuite

interpretable_ml-rsuite

IntroMachineLearningWithR-rsuite

clark-intro_ml-rsuite

hyndman-bookdown-rsuite

statistical_rethinking-rsuite

fread-benchmarks-rsuite

dataviz-rsuite

retail-segmentation-h2o-tutorial

telco-customer-churn-tutorial

sclerotinia_rsuite


R is OK for interactive use and small scripts, but I wouldn't use it for a large program. I'd use a mainstream language for most of the programming and wrap it in an R interface.

참고URL : https://stackoverflow.com/questions/1266279/how-to-organize-large-r-programs

반응형