log()
log(x, base = exp(1)) The log() function computes the natural logarithm (base e) of a number. The natural logarithm uses Euler’s number e as its base.
Syntax
log(x, base = exp(1))
log() is a C-level primitive that computes the natural logarithm by default. The function accepts a numeric vector x and an optional base argument that defaults to exp(1) — Euler’s number. When base is provided, log(x, base) computes log(x) / log(base) internally. The function is vectorized: passing a vector of length n returns a vector of n logarithms. Non-positive inputs produce -Inf for zero or NaN for negative values, each with a warning.
Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
x | numeric | — | A numeric vector or scalar |
base | numeric | exp(1) | The base for the logarithm |
Examples
Basic usage
# Natural log of e is 1
log(exp(1))
# [1] 1
# Natural log of 1 is 0
log(1)
# [1] 0
# Natural log of values > 1
log(1:5)
# [1] 0.000000 0.693147 1.098612 1.386294 1.609438
# Natural log of values < 1 (negative result)
log(0.5)
# [1] -0.6931472
The natural logarithm of e is 1 by definition, and the natural log of 1 is always 0 regardless of base — these two identities are worth memorizing because they appear constantly when interpreting model coefficients. Values greater than 1 produce positive logarithms, values between 0 and 1 produce negative logarithms, and the function grows slowly: log(10) is only about 2.3. This compression property is why log transforms are used to tame right-skewed distributions, shrinking large outliers while expanding differences among small values near zero.
Using different bases
# Log base 2
log(8, base = 2)
# [1] 3
# Log base 10
log(100, base = 10)
# [1] 2
The base argument accepts any positive number except 1. log(8, base = 2) returns 3 because 2³ = 8, and log(100, base = 10) returns 2 because 10² = 100. Mathematically, log(x, base = b) is equivalent to log(x) / log(b), so the two-argument form is a convenience rather than a separate calculation. For base 10 and base 2 specifically, the dedicated functions log10() and log2() are slightly faster because they are implemented as direct C primitives rather than going through the general two-argument path.
Common bases shortcuts
# log10() is log(x, base = 10)
log10(100)
# [1] 2
# log2() is log(x, base = 2)
log2(8)
# [1] 3
The log10() and log2() convenience functions are common enough to have their own keyboard shortcuts in RStudio. log10(100) returns 2 because 10² = 100, and log2(8) returns 3 because 2³ = 8. For bases other than e, 10, or 2, use the two-argument log(x, base = b) form. In bioinformatics, log2() is the standard for fold-change calculations because a doubling maps cleanly to a difference of 1 on the log2 scale. In engineering and physics, log10() is preferred for decibel calculations and order-of-magnitude comparisons.
Common patterns
Log-transforming skewed data
# Log-transform skewed distribution
x <- c(1, 10, 100, 1000, 10000)
log(x)
# [1] 0.000000 2.302585 4.605170 6.907755 9.210340
Log-transforming a skewed vector like c(1, 10, 100, 1000, 10000) compresses the range from five orders of magnitude into a compact scale from 0 to about 9.2. This transformation is the first step in many statistical workflows: log-transform the response variable, fit a linear model on the log scale, then exponentiate the predictions to return to the original units. The approach works because multiplicative relationships on the original scale become additive on the log scale, satisfying the linear model assumptions that raw skewed data would violate.
Geometric mean
# Geometric mean using exp(mean(log(x)))
x <- c(2, 4, 8)
exp(mean(log(x)))
# [1] 4
The geometric mean formula exp(mean(log(x))) is a classic one-liner that computes the central tendency of multiplicative data. For the vector c(2, 4, 8), the geometric mean is 4, which makes sense: 4 is the factor that sits multiplicatively between 2 and 8. This pattern appears in finance for computing average investment returns over time, in biology for averaging bacterial growth rates, and in any domain where values compound rather than add. The arithmetic mean of the same vector would be 4.67, which overstates the typical value for multiplicative processes.
Log-odds to probability
# Convert log-odds to probability
log_odds <- 0.5
exp(log_odds) / (1 + exp(log_odds))
# [1] 0.6224593
Converting log-odds to probability is a fundamental operation in logistic regression and Bayesian modeling. The formula exp(lo) / (1 + exp(lo)) maps any real-valued log-odds to a probability between 0 and 1, which is the inverse of the logit function. For a log-odds of 0.5, the probability is about 0.62 — slightly better than a coin flip. R also provides plogis(0.5) as a built-in alternative that returns the same result, but the explicit formula using exp() makes the mathematical relationship transparent.
log() vs log10() vs log2()
log() without a base argument computes the natural logarithm (base e). It is the right choice for statistical models, growth rate calculations, and mathematical derivations because the natural log has the simplest derivative (d/dx ln(x) = 1/x) and appears naturally in probability distributions.
For the most common cases in data analysis: use log() for statistical modeling and probability; use log10() for human-readable scale factors and plotting axis labels; use log2() for information theory and fold-change comparisons in genomics.
log(0) returns -Inf and log() of a negative number returns NaN with a warning. Check your data for zeros and negatives before applying a log transformation. When zeros are present, log1p(x) (which computes log(1 + x)) is a common workaround that maps zero to zero without Inf results.
The log(x, base) form accepts a custom base: log(8, base = 2) returns 3. This is equivalent to log(8) / log(2) mathematically, but the two-argument form is cleaner. For base 10 and base 2, the dedicated functions log10() and log2() are slightly faster because they are implemented as C primitives rather than calling the general log() with a base argument.
In Bayesian inference and maximum likelihood estimation, working with log-probabilities rather than probabilities avoids numerical underflow. Summing log-probabilities (log-likelihood) is standard practice: sum(log(dnorm(x, mu, sigma))) computes the log-likelihood of normally distributed data.
log() is vectorized and accepts any numeric vector. It returns -Inf for zero, NaN for negative inputs, and propagates NA values. For a column of data that includes zeros or negatives, filter or transform those values before applying log() to avoid introducing non-finite values into downstream computations.
log() with no base argument computes the natural logarithm (base e). To compute log in other bases: log(x, base = 10) for log base 10, log(x, base = 2) for log base 2 (or use the faster log2() and log10() primitives). When the base is exp(1), log() and exp() are inverses: exp(log(x)) returns x for positive values, subject to floating-point rounding.
log() is vectorized and propagates NA. It returns -Inf for zero and NaN for negative inputs (with a warning). For computing log of values that may include zero (e.g., counts in a frequency table), the common workaround is log(x + 1) — but for values very close to zero, the more numerically stable log1p(x) is preferred, since it avoids catastrophic cancellation when adding 1 to a very small number.
Working with zero and near-zero values
# log(0) and near-zero handling
log(0)
# [1] -Inf
# Warning message:
# In log(0) : NaNs produced
# Better approach for data that may include zeros
counts <- c(0, 2, 5, 0, 15)
log_counts <- log1p(counts) # log(1 + x)
log_counts
# [1] 0.000000 1.098612 1.791759 0.000000 2.772589
# Back-transform to verify
exp(log_counts) - 1
# [1] 0 2 5 0 15
Real-world datasets frequently contain zero values, especially count data from surveys or event logs. Applying log() directly to zero returns -Inf with a warning, which can silently corrupt downstream calculations. The log1p() function computes log(1 + x) in a numerically stable way that maps zero to zero and preserves small positive values accurately — note how exp(log1p(counts)) - 1 recovers the original vector exactly. This transformation is standard practice before fitting models to count data where zeros carry meaning.