Search code examples
rgithubpackage

Error while installing r package personograph from GitHub


I'm trying to install package personograph from GitHub that was formally available on CRAN. This is what I typed

install.packages("devtools")
devtools::install_github("joelkuiper/personograph")

I got this error

Error in install.packages : Updating loaded packages
Downloading GitHub repo joelkuiper/personograph@HEAD
── R CMD build ─────────────────────────────────────────────────────────────────────────────
✔  checking for file 'C:\Users\-\AppData\Local\Temp\RtmpU9Efwx\remotes3644595027e1\joelkuiper-personograph-b3249af/DESCRIPTION' (463ms)
─  preparing 'personograph': (353ms)
✔  checking DESCRIPTION meta-information ...
─  checking for LF line-endings in source and make files and shell scripts
─  checking for empty or unneeded directories
   Omitted 'LazyData' from DESCRIPTION
─  building 'personograph_0.1.3.tar.gz'
   
Installing package into ‘C:/Users/-/AppData/Local/R/win-library/4.3’
(as ‘lib’ is unspecified)
* installing *source* package 'personograph' ...
** using staged installation
** R
** inst
** byte-compile and prepare package for lazy loading
Error in x > 0 && rounded == 0 : 'length = 5' in coercion to 'logical(1)'
Error: unable to load R code in package 'personograph'
Execution halted
ERROR: lazy loading failed for package 'personograph'
* removing 'C:/Users/-/AppData/Local/R/win-library/4.3/personograph'
Warning: installation of package ‘C:/Users/-/AppData/Local/Temp/RtmpU9Efwx/file3644413f3ae3/personograph_0.1.3.tar.gz’ had non-zero exit status

Wondering what I did wrong; maybe I have too new a version of R/RStudio or I'm installing incorrectly. I know personograph got taken down from CRAN 2 years ago and I thought via GitHub might work.

I first tried to install from CRAN, then from GitHub repo, then I updated my R and RStudio versions


Solution

  • I know nothing about that package or its maintainer, but looking at the source: that package has "bad code". Specifically, in R/personograph.R#228, we see

    round.with.warn <- function(x, f=round.standard, name=NULL) {
        rounded <- f(x)
        if(x > 0 && rounded == 0) {
            warning(paste("truncating", ifelse(is.null(name), "a", name), "non-zero value of", x, "to 0"))
        }
        rounded
    }
    

    In neighboring functions (e.g., round.standard) it is permitted for x to be length > 1, so one would infer that for this as well. However, if(x > 0 ...) is just bad.

    In R-4.2.0 (see NEWS), the change was made to convert this to an error (instead of being a warning, which it had been up through 4.1).

    * Calling if() or while() with a condition of length greater than one gives
      an error rather than a warning. Consequently, environment variable 
      _R_CHECK_LENGTH_1_CONDITION_ no longer has any effect.
    

    In R-4.3.0, this was extended to include anything on the LHS of && and ||:

    * Calling && or || with LHS or (if evaluated) RHS of length greater than one 
      is now always an error, with a report of the form
            'length = 4' in coercion to 'logical(1)'
      Environment variable _R_CHECK_LENGTH_1_LOGIC2_ no longer has any effect.
    

    Looking at the personograph.R file again, we see that round.with.warn is called once in personograph(). Since that function has documentation with @examples code that is not wrapped in \dontrun{..} (personograph.R#L285-L293)

    #' @examples
    #' data <- list(first=0.9, second=0.1)
    #' personograph(data)
    #' # With colors
    #' personograph(data, colors=list(first="red", second="blue"))
    #' # With different icon.style
    #' personograph(data, icon.style=4) # numeric from 1-11
    #' # Plot a thousand in a 20x50 grid
    #' personograph(data, n.icons=1000, dimensions=c(20,50), plot.width=0.75)
    

    This example code is run when the package is checked for installation. Because the inner round.with.warn is broken, the package installation fails.

    Given that the last commit for that package (b3249af) was made on Nov 6, 2015 (8+ years ago as of this writing), and none of the issues after that point have received any comment from the author, I think it unlikely that the package is being maintained. (CRAN archived it on 2022-04-28 due to "email to the maintainer is undeliverable". And likely due to unresolved build-errors.)

    I think your three options at this point:

    1. Find another way to do what you want, forego the use of the personograph package.
    2. Fork the package and bring it up-to-date. Realistically, there may be no need to push to CRAN, so this option could easily be git clone https://github.com/joelkuiper/personograph.git to a directory local to your computer, fix the code, and only install it locally with no pushes back to any repo.
    3. Pay somebody to do #2 for you.

    (Okay ... technically you may be able to downgrade to a version of R that doesn't have these restrictions. That would set you back many years of R's development, and would likely make most other packages you may be using uninstallable (or very difficult to install) for other reasons. I don't recommend this path.)


    There is a little irony in the `round.with.warn` function: the `if(x > 0 ..)` is clearly missing the notion that `if` conditionals cannot be vectorized. However, that function later uses `ifelse(is.null(name), ..)`, which while it works is (IMHO) also bad code. `is.null(.)` always returns length-1, so using `ifelse` (not "primitive", has a non-zero stack cost, and certainly has baggage such as https://stackoverflow.com/q/6668963/3358272) is applying a vectorizing logic to something that will never need it. That _should_ have been `if (is.null(name)) "a" else name` or perhaps a much shorter hack with `c(name, "a")[[1]]` (assuming length-1).