Why not r via conda?

R with conda works great! Unfortunately, the is 0 or less than 0 support from the rstudio community on this. One commenter on a post of mine said that I was wrong to call conda a package manager. Oh golly.

There are a few tricks to keep in mind:

  1. When you use R with conda you need to stick to conda as much as you can. DON'T LET R INSTALL PACKAGES FOR YOU. In other words ALWAYS USE CONDA TO INSTALL THE PACKAGES YOU NEED unless there is not a conda recipe for that package. In that case, see below.

  2. Take great care in terms of which conda channels you use. After extensive experimentation and discussion with channel maintainers, I have learned the following (and I wish this information was more transparently out there):

  • R versions in different channels are often not compatible as they are compiled with different internals.
  • The anaconda channel is maintained by continuum. The r channel is...well I don't really understand but I think it's some kind of subset of the anaconda channel. These channels are probably compatible.
  • The conda-forge, bioconda, and defaults channels are open-source channels. They are largely compatible with the following caveat. In your .condarc, you should always use the following order: 1. conda-forge, 2. bioconda, 3. defaults. If you stick to that order, you should not have any problems.
  • Do not mix proprietary channels (anaconda,r) with open-source channels (conda-forge, bioconda, defaults). Problems will arise.
  1. When you need packages that are not available in the channel set you are using, you must install them by hand into an external location outside of the conda environment. As an example, I have a directory /home/balter/R35. When I want to install a package by hand, I do install.packages(<some_pkg>, lib='/home/bater/R35). Other install methods such as biocLite and install.github wrap install.packages, so will accept the lib argument even if it's not explicitly noted in the docs.

There is a bit more to this as in the process of installing <some_pkg> other r packages may be installed. The installer will put them into the directory specified with lib. This is ok, but many of the dependencies could actually be installed with conda which is preferable. Consequently, when installing an R package externally (and if you need to do this a lot, then conda may not be the solution for you), I look up the dependencies in the docs and install those first with conda.

Finally, you will need to add your external library to your .lib.Paths. However, you need to make sure your conda path is first. Thus:

.libPaths(new=c('<conda home>/envs/env_name/lib/R/library', '<path to external>')

Finally, I put this function (which you will have to edit somewhat) in my .Rprofile to make sure everything works all the time, which once I figured all this out IT HAS DONE WITH 100% CONSISTENCY AND NO PROBLEMS.

(ds35) balter@little-d:~$ cat .Rprofile
options(repos=structure(c(CRAN="https://ftp.osuosl.org/pub/cran/")))

startCondaEnv = function(env_name, lib='/home/balter/R')
{
        cat("pointing to conda env:", env_name, "and lib location", lib, "\n")

        r_lib_path = lib
        if (env_name == "" || env_name == "base")
    {
                #print("using default base env")
                conda_lib_path = file.path('/home/balter/conda/lib/R/library')
        }else
        {
                conda_lib_path = file.path('/home/balter/conda/envs', env_name, 'lib/R/library')
        }

        #cat('conda_lib_path: ', conda_lib_path, '\n')

        .libPaths(new=c(conda_lib_path, r_lib_path))

        #cat(".libPaths():\n")
        print(.libPaths())
}


current_conda_env = Sys.getenv('CONDA_DEFAULT_ENV')
cat('current_conda_env:', current_conda_env, '\n')

current_conda_prefix = Sys.getenv('CONDA_PREFIX')
cat('current_conda_prefix:', current_conda_prefix, '\n')

if (current_conda_env != "")
{
        r_version = R.Version()
        r_version = paste0(r_version$major, '.', r_version$minor)

        if (r_version == '3.5.1')
        {
                r_lib_path = '/home/balter/R35'
        }else
        if (r_version == '3.4.11')
        {
                r_lib_path = '/home/balter/R34'
        }else
        {
                message("no compatible lib")
                r_lib_path = ''
        }

        #cat("env: ", current_conda_env, ", prefix: ", current_conda_prefix, "\n")
        conda_env_lib = file.path(current_conda_prefix,'lib/R/library')
        startCondaEnv(current_conda_env, lib=r_lib_path)
}else
{
        print("no conda env")
}

Not the most beautiful code, but it works, and if you have any ideas for improvement, please do comment. Obviously, this is for linux and you will need to write your own for Windows.

Best of luck and feel free to respond with more questions as this will help me refine this process which I eventually hope to add to some online docs somewhere.

8 Likes