Skip to contents

Introduction and notation

This vignette contains information on installing and getting information about R packages. It also explains how to obtain the source code of R functions.

In this vignette, text between angled brackets (<...>) is used to refer to text that should be replaced with specific text to get working code or working file paths. For example, <pkgname> is used as a place holder to refer to a package name and should be replaced with utils if you want to obtain information about package utils, and with methods if you want to obtain information about package methods. Similarly, <funcname> is used as a place holder to refer to a function name that should be filled in with a specific function name to get working code.

In this vignette, calls to functions are frequently written in the form <pkgname>::<funcname>(), to make clear which package is used and, through the brackets, that a function is indicated. In normal code, one would use library(<pkgname>) followed by <funcname>(). For example, in this vignette the notation utils::citation() is used to show how to cite R, indicating that the function citation() is defined in package utils. In normal code, one would use library(utils) followed by citation() where that is needed.

R packages

An R package is a standardized collection of material extending R by providing code, data, or documentation.

The base packages are always installed together with R. The recommended packages are installed with binary distributions of R. Together, the base and recommended packages are the ‘high priority’ packages. Since R 4.4.0, tools::standard_package_names() contains a list with the names of these packages. To see which high-priority packages are currently installed, run sort(unname(installed.packages(priority = "high")[, "Package"])). Package ‘translations’ is not a recommended package, but will be installed if that option is set during the installation of R.

Installing packages

To install a package, run R or RStudio as administrator: right-click on the R or RStudio icon and select Run as administrator. Packages can be obtained from several websites, called ‘repositories’, such as CRAN, BioConductor, and GitHub, as discussed in the next sections. After installing a package, you need to run library(<pkgname>) to be able to use the functions of that package.

CRAN

The Comprehensive R Archive Network (CRAN) is the main repository of R packages. The following code can be used to install packages from CRAN:

pkgs_new <- c(<pkgname>, <pkgname>)
# Select packages from 'pkgs_new' that are not installed or not functional
pkgs_install <- pkgs_new[!vapply(X = pkgs_new, FUN = requireNamespace,
                                 FUN.VALUE = logical(1), quietly = TRUE)]
if(length(pkgs_install) > 0L) {
  install.packages(pkgs = pkgs_install, lib = .libPaths(), dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}

CRAN has thematic package collections known as task views. To install all core packages of a task view, install package ctv and run ctv::install.views("<taskviewname>", coreOnly = TRUE). To update these packages, use ctv::update.views("<taskviewname>", coreOnly = TRUE).

Packages from CRAN that have been recently archived are available at CRANhaven.

BioConductor

The Bioconductor repository releases versions that contain specific versions of packages from CRAN and BioConductor that are consistent with each other and with a specific version of R, preventing version conflicts between R packages.

The following code can be used to install packages from BioConductor release version 3.23. This code installs the BiocManager package from CRAN that is then used to install packages from Bioconductor and CRAN and, through remotes::install_github() (see the next section), from GitHub:

pkgs_new <- c(<pkgname>, <pkgname>)
if(!requireNamespace("BiocManager", quietly = TRUE)) {
  install.packages(pkgs = "BiocManager", lib = .libPaths(), dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}
BiocManager::install(pkgs = pkgs_new, lib = .libPaths(), dependencies = NA,
                     build_vignettes = TRUE,
                     type = getOption("pkgType"), verbose = getOption("verbose"),
                     update = FALSE, ask = TRUE, checkBuilt = TRUE,
                     force = FALSE, version = "3.23")

Bioconductor also has thematic package collections known as BiocViews.

Github

The following code can be used to install packages from GitHub: it installs the remotes package that is needed to install packages from GitHub. If installing packages fails, trying with arguments force = TRUE to re-install possibly broken dependencies and build_vignettes = FALSE to not install vignettes might help.

grep(pattern = "/", x = pkgs_new, value = TRUE) selects the elements of pkgs_new which contain a slash because remotes::install_github() only works if each element of pkgs contains the author name and repository name (e.g., "JesseAlderliesten/checkrpkgs") or the full URL to a package (e.g., "https://github.com/JesseAlderliesten/checkrpkgs"). To match names in such formats to package names returned by utils::installed.packages(), use basename(pkgs_new) instead of pkgs_new to select the last part of the name (e.g., "checkrpkgs" instead of "JesseAlderliesten/checkrpkgs"): pkgs[!(basename(pkgs) %in% installed.packages()[, "Package"])].

pkgs_new <- c("JesseAlderliesten/checkrpkgs",
              "https://github.com/JesseAlderliesten/progutils")
if(!requireNamespace("remotes", quietly = TRUE)) {
  install.packages(pkgs = "remotes", lib = .libPaths(), dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}
remotes::install_github(repo = grep(pattern = "/", x = pkgs_new, value = TRUE),
                        dependencies = NA, upgrade = "ask", force = FALSE,
                        quiet = FALSE, build_vignettes = TRUE, lib = .libPaths(),
                        verbose = getOption("verbose"))

Other repositories, mirrors

Examples of other repositories for R packages are:

The websites of these repositories include instructions how to install packages from them, and repositories can be selected using utils::setRepositories(). The following code shows how to install packages from R-Forge as an example:

pkgs_new <- c(<pkgname>, <pkgname>)
# Select packages that are currently not installed or not functional
pkgs_install <- pkgs_new[!vapply(X = pkgs_new, FUN = requireNamespace,
                                 FUN.VALUE = logical(1), quietly = TRUE)]
if(length(pkgs_install) > 0L) {
  install.packages(pkgs = pkgs_install, lib = .libPaths(),
                   repos = "https://r-forge.r-project.org/", dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}

Mirror websites (mirrors) are websites hosted in various parts of the world with the same content as the main website. Using a nearby mirror allows for faster downloads. Mirrors of repositories can be selected using utils::setRepositories().

CRAN mirrors, with information about their status that is also available from within R through utils::getCRANmirrors(), can be selected using utils::chooseCRANmirror(). However, RStudio uses the RStudio CRAN mirror with its own global distribution, which is signalled by the message 'getOption("repos")' replaces Bioconductor standard repositories, see 'help("repositories", package = "BiocManager")' for details.

Bioconductor mirrors, with information about their status, can be selected using BiocManager::repositories() or utils::chooseBioCmirror(), although the RStudio CRAN mirror is used in RStudio (see the preceding paragraph).

Updating packages

Updating out-of-date packages prevents compatibility issues between already-installed and newly-installed packages.

CRAN

For R packages from CRAN, versions can be compared using diffify and a chronological overview of changes is available at CRANberries. To get the version number of an installed package, run utils::packageVersion("<pkgname>").

The following code can be used to install the latest version of packages from CRAN (but note this changes the version of already-installed packages, which might be undesirable):

utils::update.packages(lib.loc = .libPaths(), ask = TRUE, dependencies = NA,
                       verbose = getOption("verbose"), quiet = FALSE,
                       checkBuilt = TRUE, type = getOption("pkgType"))

Bioconductor

The following code can be used to update packages to a specific BioConductor release (here version 3.23):

if(!requireNamespace("BiocManager", quietly = TRUE)) {
  install.packages(pkgs = "BiocManager", lib = .libPaths(), dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}
BiocManager::install(pkgs = character(), lib = .libPaths(), dependencies = NA,
                     build_vignettes = TRUE, 
                     type = getOption("pkgType"), verbose = getOption("verbose"),
                     update = TRUE, ask = TRUE, checkBuilt = TRUE, force = FALSE,
                     version = "3.23")

Installing old versions

Installing old versions of a package might require installing Rtools to build the packages from source, see the section ‘Rtools’ in the vignette Installing R, Rtools and RStudio: vignette("install_r", package = "checkrpkgs").

CRAN

The following code can be used to install an old version of a package from CRAN, using package remotes:

if(!requireNamespace("remotes", quietly = TRUE)) {
  install.packages(pkgs = "remotes", lib = .libPaths(), dependencies = NA,
                   type = getOption("pkgType"), verbose = getOption("verbose"),
                   quiet = FALSE)
}
remotes::install_version(package = "deSolve", version = "1.40", dependencies = NA,
                         upgrade = "ask", quiet = FALSE, build_vignettes = TRUE,
                         lib = .libPaths(), verbose = getOption("verbose"))

Alternatively, visit the installation page of a package from CRAN, go to Downloads > Old sources > <pkgname> archive and find the appropriate URL pointing to an older version to install it using base R. For example, to install version 1.40 of package deSolve:

install.packages(
  pkgs = "https://cran.r-project.org/src/contrib/Archive/deSolve/deSolve_1.40.tar.gz",
  lib = .libPaths(), repos = NULL, dependencies = NA,
  type = getOption("pkgType"), verbose = getOption("verbose"),
  quiet = FALSE)

Bioconductor

Older versions of packages from Bioconductor can be installed by changing the value of argument version of BiocManager::install() (e.g., BiocManager::install(pkgs = "deSolve", version = "3.22") to indicate the version of deSolve included in BioConductor version 3.22) but that only works when using the version of R for that specific version of bioConductor, see the overview of Bioconductor versions with the corresponding R version. Information on these older packages can be found by visiting the appropriate version of Bioconductor, e.g., https://bioconductor.org/packages/3.22/BiocViews.html.

Troubleshooting

Installing packages

  • If the warnings lib = <pkgname> is not writeable or 'lib' element <element from .libPaths()> is not a writable directory occur, you probably forgot to run R (or RStudio) as administrator. Close R (RStudio), right-click on the R or RStudio icon and select Run as administrator to start it as administrator.

  • If the question Do you want to install from sources the packages which need compilation? is asked (in a new window), accompanied by the remark There are binary versions available but the source versions are later and an overview in the console of the binary and source versions indicating if these need compilation, you should choose No if you have not installed Rtools: you will then get slightly less up to date package versions but a faster installation.

    If you want the latest version without using Rtools, you can try again a few days later: it usually takes a bit longer for the binaries (i.e., the package versions that do not have to be build from source) from CRAN and Bioconductor to be updated than for the source versions used by Rtools.

    If you have installed Rtools you can choose Yes to install the latest package versions by building them from source. To install Rtools, see the section ‘Rtools’ in the vignette Installing R, Rtools and RStudio: vignette("install_r", package = "checkrpkgs").

  • The warning package '<pkgname>' is not available (for R version x.y.z) can have many reasons. First double-check the package name (which is case-sensitive). Then check possible other reasons mentioned in this stackoverflow answer.

  • If installing packages fails, try with arguments force = TRUE to re-install possibly broken dependencies and build_vignettes = FALSE to not install vignettes.

Using packages

  • If a package appears not to be installed when you want to use a function from it (e.g., you get the error could not find function "<funcname>"), remember you need to run library(<pkgname>) to be able to use its functions.

  • If a package is not functional, re-install it using argument force = TRUE to re-install possibly broken dependencies. You can also use checkrpkgs::get_details_pkgs(pkgs = <pkgname>) to check which dependencies and system requirements it has and then use checkrpkgs::check_pkgs(pkgs = <pkgnames>) to check if all the dependencies are installed and functional.

  • If the warning package <pkgname> was built under R version 'x.y.z' occurs, you installed a binary package (i.e., not by building from source) that was prepared (‘compiled’) for an earlier version of R than the version of R you are currently using (run getRversion() to see your current R version). The warning is issued because packages are not tested on versions of R that are older than the version they were built on. Therefore it is best to update R when installing packages.

  • If errors occur when loading packages that require Java, make sure the 64-bit version of Java is installed on 64-bit PCs.

Information about packages

Information about packages can be obtained from the internet before the packages are installed, as well as from within R after the packages are installed.

Not-yet-installed packages

The reference manual is a PDF-file with all the help files of the standard and recommended packages. The manuals and help pages of all packages from CRAN can be searched online, or from within R using utils::RSiteSearch(). In addition, utils::help.search() can be used to search the help system using fuzzy matching or regular expressions, which can be disabled by setting argument agrep to FALSE to search faster and return fewer results: utils::help.search(..., agrep = FALSE).

tools::CRAN_package_db() gives information about packages available from CRAN; BiocManager::available() gives the names of packages available from BioConductor.

The source code of base R packages can be obtained from GitHub (see the section Repositories below), and installation pages of packages on CRAN frequently contain links to GitHub pages where their source code can be viewed.

For (not necessarily installed) packages from CRAN, use tools::package_dependencies(packages = "<pkgname>", recursive = TRUE) to see dependencies (i.e., which packages are required by package <pkgname>) and tools::dependsOnPkgs(pkgs = "<pkgname>", recursive = TRUE) to see reverse dependencies (i.e., which packages require package <pkgname>). NULL is returned for packages that are not found, whereas character(0) is returned for packages that do not have any dependencies.

Already-installed packages

The locations where R installs packages, and where it looks for installed packages, can be obtained with .libPaths(), and the names of all installed packages can be obtained with list.files(path = .libPaths(), recursive = FALSE). The repository from which a package was installed can be obtained from the Repository and URL fields of package descriptions: checkrpkgs::get_details_pkgs(pkgs = <pkgname>). The output of checkrpkgs::get_details_pkgs() can be used to re-install packages after installing a new version of R.

Information about a package and its functions is available from within R after the package has been installed and loaded (i.e., library(<pkgname>) has been run):

  • Citation: utils::citation("<pkgname>"), with utils::citation() to cite R itself.
  • Function overview: ls(getNamespace("<pkgname>")) returns a character vector with the function names (ignoring names that start with a dot, which by convention are for internal use in packages; ls(getNamespace("<pkgname>"), all.names = TRUE) includes those function names in the returned character vector); help(package = "<pkgname>") gives an overview with links to their help-pages if there is a file <pkgname>.R in folder <pgkname>\R.
  • Help page: help(topic = "<pkgname>").
  • Version: utils::packageVersion("<pkgname>").
  • Vignettes: show them in a browser through utils::browseVignettes(package = "<pkgname>") or list them with utils::vignette(package = "<pkgname>").

Information about functions, methods, and classes can also be obtained (see also the section Getting the source code below):

  • Arguments: args("<funcname>").
  • Help page: help("<funcname>"); indicate the package to distinguish functions with the same name from different packages: help("<funcname>", package = "<pkgname>"); use quotes around the name of an operator to get its help page: help("%in%").
  • Methods: for a generic class: utils::methods(class = "<classname>"); for a generic function: utils::methods("<funcname>"); for S3-methods: attr(utils::methods(class = "<classname>"), "info"); for S4-methods: methods::showMethods(classes = "<classname>", where = getNamespace("<pkgname>")).
  • Objects (including functions) whose name contains a certain string: utils::apropos("<string>").

Which packages are used?

The function loadedNamespaces() shows which packages are loaded. To see which packages are used in a script, look for ::, :::, library, require, and namespace (e.g., loadNamespace(), requireNamespace()). Various packages have their own way to create dependencies on packages, see the overview at pak::scan_deps().

To see which packages are mentioned in comments, also look for:

Getting the source code

Acknowledgements

Partly based on:

Repositories

The source code of the base R packages, for the development, current, and older versions of R, is available at CRAN and at the SVN-project. Searching the source code of the development version is easiest using the GitHub mirror of the SVN-project, see also the documentation on searching GitHub.

The source code of add-on packages from CRAN can be searched at METACRAN, an unofficial CRAN mirror. Alternatively, download the source file from section Downloads of the CRAN page. The source files have been compressed into a tar file so you have to extract the files (right-click on the downloaded file and choose extract all).

The source code of add-on packages from BioConductor in the current version or in the development-version is available here.

The source code of add-on packages from GitHub can be viewed directly on GitHub, or after downloading the code to your computer by clicking the green Code button on the repository page (e.g., https://github.com/JesseAlderliesten/checkrpkgs), choosing Download ZIP, and unzipping the downloaded file (right-click on the file and choose extract all).

Basic method

The simplest way to obtain the source code of a function is to type the name of the function, without the brackets, and press Enter. For example, to see what happens when using sd() to calculate the standard deviation:

sd
#> function (x, na.rm = FALSE) 
#> sqrt(var(if (is.vector(x) || is.factor(x)) x else as.double(x), 
#>     na.rm = na.rm))
#> <bytecode: 0x55e490f6aac0>
#> <environment: namespace:stats>

Some special cases:

  • To distinguish functions with the same name from different packages, specify the package followed by two colons: <pkgname>::<funcname>.
  • For non-exported functions, specify the package followed by three colons: <pkgname>:::<funcname> (using only two colons, will result in the error '<funcname>' is not an exported object from 'namespace:<pkgname>'. Non-exported functions should not be used in code because they might change.
  • For operators such as %in% (see help("match") which start with a symbol, use backticks (`) around the name:
`%in%`
#> function (x, table) 
#> match(x, table, nomatch = 0L) > 0L
#> <bytecode: 0x55e48f430d00>
#> <environment: namespace:base>

getAnywhere

A more robust alternative to the basic method outlined above is to use getAnywhere("<funcname>"), which looks in more places and finds internal functions without the need to specify in which package a function is defined. Although the quotes around the function name are not necessary when looking for the source code of normal functions, they are required when looking for the source code of operators such as %in%, such that it is most robust to always use them.

UseMethod

If getAnywhere("<funcname>") returns UseMethod("<funcname>"), the function has different methods for different object classes and is S3-generic. First use methods("<funcname>") to get an overview of the available methods; then obtain the source code of a particular method by using getAnywhere("<function.class>"), where <function.class> is an item from the overview that was returned by methods("<funcname>"). The advantage over simply using "<function.class>" is that getAnywhere("<function.class>") also works for functions that are not exported, which is indicated in the overview of methods(<funcname>) by an asterisk and the remark Non-visible functions are asterisked.

For example, UseMethod("mean") in the output of getAnywhere("mean") indicates mean is an S3-generic:

getAnywhere("mean")
#> A single object matching 'mean' was found
#> It was found in the following places
#>   package:base
#>   namespace:base
#> with value
#> 
#> function (x, ...) 
#> UseMethod("mean")
#> <bytecode: 0x55e4917063f8>
#> <environment: namespace:base>

First use methods("mean") to get an overview of the available methods:

methods("mean")
#> [1] mean.Date     mean.default  mean.difftime mean.POSIXct  mean.POSIXlt 
#> [6] mean.quosure*
#> see '?methods' for accessing help and source code

The output shows, among others, the methods mean.Date and mean.default. Then use getAnywhere("mean.Date") to see the source code of the method mean used with objects of class Date.

getAnywhere("mean.Date")
#> A single object matching 'mean.Date' was found
#> It was found in the following places
#>   package:base
#>   registered S3 method for mean from namespace base
#>   namespace:base
#> with value
#> 
#> function (x, ...) 
#> .Date(mean(unclass(x), ...))
#> <bytecode: 0x55e492ac0da0>
#> <environment: namespace:base>

Or use getAnywhere("mean.default") to see the source code of the method mean used with objects of classes not listed in the output of methods("mean"):

getAnywhere("mean.default")
#> A single object matching 'mean.default' was found
#> It was found in the following places
#>   package:base
#>   registered S3 method for mean from namespace base
#>   namespace:base
#> with value
#> 
#> function (x, trim = 0, na.rm = FALSE, ...) 
#> {
#>     if (!is.numeric(x) && !is.complex(x) && !is.logical(x)) {
#>         warning("argument is not numeric or logical: returning NA")
#>         return(NA_real_)
#>     }
#>     if (isTRUE(na.rm)) 
#>         x <- x[!is.na(x)]
#>     if (!is.numeric(trim) || length(trim) != 1L) 
#>         stop("'trim' must be numeric of length one")
#>     n <- length(x)
#>     if (trim > 0 && n) {
#>         if (is.complex(x)) 
#>             stop("trimmed means are not defined for complex data")
#>         if (anyNA(x)) 
#>             return(NA_real_)
#>         if (trim >= 0.5) 
#>             return(stats::median(x, na.rm = FALSE))
#>         lo <- floor(n * trim) + 1
#>         hi <- n + 1 - lo
#>         x <- sort.int(x, partial = unique(c(lo, hi)))[lo:hi]
#>     }
#>     .Internal(mean(x))
#> }
#> <bytecode: 0x55e492ac0390>
#> <environment: namespace:base>

standardGeneric

If getAnywhere("<funcname>") returns standardGeneric("<funcname>"), the function has different S4-methods (see help("Introduction", package = "methods")) for different object classes. Use showMethods("<funcname>") to get an overview of the available methods in all loaded packages, or use <pkgname>:::<funcname> to get an overview of the available methods from package <pkgname>. Finally, provide the function name as argument f and the selected method as a character vector to argument signature (see also help("signature")) of function getMethod() to obtain the source code of a particular method: getMethod(f = "<funcname>", signature = c(target = "<classname>", current = "<classname>")).

The example below shows how to find the source code of method cbind2() used by the Matrix package to combine two matrices that both have the Matrix class as defined by package Matrix.

library(Matrix)
getAnywhere("cbind2")
#> A single object matching 'cbind2' was found
#> It was found in the following places
#>   package:Matrix
#>   package:methods
#>   namespace:methods
#> with value
#> 
#> new("standardGeneric", .Data = function (x, y, ...) 
#> standardGeneric("cbind2"), generic = "cbind2", package = "methods", 
#>     group = list(), valueClass = character(0), signature = c("x", 
#>     "y"), default = NULL, skeleton = (function (x, y, ...) 
#>     stop(gettextf("invalid call in method dispatch to '%s' (no default method)", 
#>         "cbind2"), domain = NA))(x, y, ...))
#> <bytecode: 0x55e490f8e750>
#> <environment: 0x55e48fd3d428>
#> attr(,"generic")
#> [1] "cbind2"
#> attr(,"generic")attr(,"package")
#> [1] "methods"
#> attr(,"package")
#> [1] "methods"
#> attr(,"group")
#> list()
#> attr(,"valueClass")
#> character(0)
#> attr(,"signature")
#> [1] "x" "y"
#> attr(,"default")
#> `\001NULL\001`
#> attr(,"skeleton")
#> (function (x, y, ...) 
#> stop(gettextf("invalid call in method dispatch to '%s' (no default method)", 
#>     "cbind2"), domain = NA))(x, y, ...)
#> attr(,"class")
#> [1] "standardGeneric"
#> attr(,"class")attr(,"package")
#> [1] "methods"

# standardGeneric("cbind2") indicating that cbind2() is an S4 function, so use
# showMethods("cbind2") to get an overview of the different methods:
showMethods("cbind2")
#> Function: cbind2 (package methods)
#> x="ANY", y="ANY"
#> x="ANY", y="missing"
#> x="matrix", y="Matrix"
#> x="Matrix", y="matrix"
#> x="Matrix", y="Matrix"
#> x="Matrix", y="missing"
#> x="Matrix", y="NULL"
#> x="Matrix", y="vector"
#> x="NULL", y="Matrix"
#> x="vector", y="Matrix"

# To get the source code of 'cbind2' used with two matrices that both have the
# 'Matrix' class defined by package 'Matrix'
getMethod(f = "cbind2", signature = c(x = "Matrix", y = "Matrix"))
#> Method Definition:
#> 
#> function (x, y, ...) 
#> cbind.Matrix(x, y, deparse.level = 0L)
#> <bytecode: 0x55e492daa530>
#> <environment: namespace:Matrix>
#> 
#> Signatures:
#>         x        y       
#> target  "Matrix" "Matrix"
#> defined "Matrix" "Matrix"

.Internal or .Primitive

If getAnywhere("<funcname>") returns .Internal or .Primitive, the function is internal or primitive. The source code of such functions can be viewed at code repositories, or on your computer if you have installed R from source using Rtools (see the section ‘Rtools’ in the vignette Installing R, Rtools and RStudio: vignette("install_r", package = "checkrpkgs")).

Locate the file src/main/names.c and look in the first column for the name of the R function to find the appropriate c-entry which is given in the second column of that file. Then either search for that c-entry using the GitHub search, or manually locate the c-file (the name of the file is the c-entry without the prefix do_) in src/main to get the file with the source code.

For example, getAnywhere("matrix") shows, among others, the line .Internal(matrix(data, nrow, ncol, byrow, dimnames, missing(nrow), missing(ncol))). The file src/main/names.c has as entry with matrix in the first column: {"matrix", do_matrix, 0, 11, 7, {PP_FUNCALL, PREC_FN, 0}} Searching src/main for matrix gives file array.c as one of the results. That file contains the source code of matrix. Similarly, getAnywhere("log10") shows function (x) .Primitive("log10"). The file src/main/names.c has as entry with log10 in the first column: {"log10", do_log1arg, 10, 1, 1, {PP_FUNCALL, PREC_FN, 0}}. Searching src/main for log1arg gives file arithmetic.c as one of its results. That file contains the source code of log10.

Sometimes an R-function is defined in a file that defines multiple functions and thus has a general name. Then the file with c-code will have a similar general name. For example, the source code of make.names() is defined in src/library/base/R/character.R which contains (among others) the code .Internal(make.names(names, allow_)), and the c-code for do_makenames() is in file src/main/character.c.

.Call

If getAnywhere("<funcname>") returns code that contains .Call(...), the function contains a call to C or C++ code. Although the file src/<pkgname>.h (e.g., src/methods.h if code is from package methods) contains an overview of the C or C++ code included in a package, your best bet for finding the source code is searching the relevant part of the GitHub repository (e.g., https://github.com/r-devel/r-svn/tree/main/src/library/methods/src for code from package methods), or installing the package from source (see the section ‘Rtools’ in the vignette Installing R, Rtools and RStudio: vignette("install_r", package = "checkrpkgs")) and searching in the src folder of the downloaded code.

Documentation and help