R Warning: longer object length is not a multiple of shorter
Warning: longer object length is not a multiple of shorter object length appears when R tries to combine two vectors of different lengths and the shorter one doesn't divide evenly into the longer one. R still recycles, but the result is likely wrong.
The Warning
# Reproduce the warning:
x <- c(1, 2, 3, 4, 5) # length 5
y <- c(10, 20) # length 2
result <- x + y
cat("x:", x, "\n")
cat("y:", y, "\n")
cat("x + y:", result, "\n")
cat("R recycled y as: 10, 20, 10, 20, 10\n")
cat("5 is not a multiple of 2, so R warns you.\n")
How Vector Recycling Works
R automatically repeats the shorter vector to match the longer one:
# When lengths divide evenly: NO warning
a <- c(1, 2, 3, 4, 5, 6) # length 6
b <- c(10, 20, 30) # length 3 (divides into 6)
cat("No warning:", a + b, "\n")
cat("b recycled as: 10, 20, 30, 10, 20, 30\n\n")
# When lengths don't divide evenly: WARNING
c <- c(1, 2, 3, 4, 5) # length 5
d <- c(10, 20, 30) # length 3 (doesn't divide into 5)
cat("With warning:", c + d, "\n")
cat("d recycled as: 10, 20, 30, 10, 20 (truncated!)\n")
Recycling with length-1 vectors (scalars) is intentional and never warns: x * 2 multiplies every element by 2.
Cause 1: Accidentally Unequal Vectors
The most common case — you meant the vectors to be the same length:
names <- c("Alice", "Bob", "Carol", "Dave")
scores <- c(88, 92, 75) # Oops! Forgot Dave's score
cat("names:", length(names), "elements\n")
cat("scores:", length(scores), "elements\n")
# Creating a data frame would error:
# data.frame(name = names, score = scores)
# Fix: make sure vectors are the same length
scores_fixed <- c(88, 92, 75, 81) # add the missing score
df <- data.frame(name = names, score = scores_fixed)
print(df)
Fix: Check length() of both vectors. Ensure they match before combining. data.frame() is stricter and will error instead of warning.
Cause 2: Conditional Subsetting Creates Unequal Lengths
Filtering one vector but not its pair:
x <- 1:10
y <- 11:20
# Filter only x, forget to filter y
x_filtered <- x[x > 5]
cat("x_filtered:", x_filtered, "(length", length(x_filtered), ")\n")
cat("y:", y, "(length", length(y), ")\n")
# This would recycle with a warning
result <- x_filtered + y
cat("Mismatched addition:", result, "\n")
# Fix: apply the same filter to both
mask <- x > 5
x_fix <- x[mask]
y_fix <- y[mask]
cat("\nFiltered both:", x_fix + y_fix, "\n")
Fix: Apply the same logical filter to all related vectors. Or store them in a data frame and subset rows.
Cause 3: Off-by-One from Diff, Lag, or Slice Operations
Functions like diff() return a vector one element shorter:
values <- c(10, 15, 13, 20, 18)
changes <- diff(values) # length 4, not 5
cat("values:", values, "(length", length(values), ")\n")
cat("changes:", changes, "(length", length(changes), ")\n")
# Trying to combine them would warn:
# data.frame(value = values, change = changes) # Error: different lengths
# Fix option 1: pad with NA
changes_padded <- c(NA, changes)
cat("Padded:", changes_padded, "\n")
# Fix option 2: trim the original
values_trimmed <- values[-1]
cat("Trimmed:", values_trimmed, "\n")
cat("Now both length:", length(values_trimmed), "\n")
Fix: Pad the shorter vector with NA at the start/end, or trim the longer vector to match.
Cause 4: Matrix Operations with Wrong Dimensions
mat <- matrix(1:12, nrow = 3, ncol = 4)
cat("Matrix (3x4):\n")
print(mat)
# Adding a vector of wrong length
v <- c(10, 20, 30, 40, 50) # length 5, matrix has 12 elements
# mat + v # Warning: 12 is not a multiple of 5
# Fix: match vector length to rows or columns
row_add <- c(100, 200, 300) # length 3 = nrow
col_add <- c(10, 20, 30, 40) # length 4 = ncol
# Adding to each column (recycles down rows)
cat("Add by row:", "\n")
print(mat + row_add)
Fix: Make sure vector length matches the matrix dimension you're operating on.
Cause 5: Merge or Comparison of Different-Length Groups
group_a <- c(85, 90, 78, 92) # 4 students
group_b <- c(88, 76, 95) # 3 students
# Comparing directly warns:
# group_a - group_b # Warning
# Fix: don't compare element-wise when groups have different sizes
cat("Group A mean:", mean(group_a), "\n")
cat("Group B mean:", mean(group_b), "\n")
cat("Difference in means:", mean(group_a) - mean(group_b), "\n")
# Or use a proper statistical test
t_result <- t.test(group_a, group_b)
cat("t-test p-value:", t_result$p.value, "\n")
Fix: Use summary statistics or statistical tests for comparing groups of different sizes. Don't do element-wise operations.
Practice Exercise
# Exercise: This code produces a recycling warning. Fix it properly.
months <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
revenue <- c(100, 120, 115, 130) # Only Q1 data
# This warns because 12 is not a multiple of 4... wait, it IS a multiple.
# But the intent is wrong — we only have 4 months of data, not 12.
# Fix: only use matching data
Click to reveal solution
```r
months <- c("Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec")
revenue <- c(100, 120, 115, 130) # Only Q1 data
# Problem: recycling would silently repeat Q1 data for all 12 months!
# Even though 12 is a multiple of 4, the result is WRONG.
# Fix: only combine matching data
q1_months <- months[1:4]
q1_data <- data.frame(month = q1_months, revenue = revenue)
cat("Q1 data only:\n")
print(q1_data)
# Or pad revenue with NA for missing months
full_revenue <- c(revenue, rep(NA, 8))
full_data <- data.frame(month = months, revenue = full_revenue)
cat("\nFull year (with NAs for missing months):\n")
print(full_data)
**Explanation:** This is a subtle case. R would NOT warn here because 12 is a multiple of 4 — so recycling happens silently. But the result is wrong: it repeats Q1 revenue for Q2, Q3, Q4. The fix is to either only use 4 months or pad with NAs. Silent recycling without a warning is the most dangerous case.
Summary
Cause
Fix
Prevention
Unequal vectors
Match lengths before combining
Check length() on both
Filtered one but not the other
Apply same filter to all
Store related vectors in a data frame
diff/lag returns shorter vector
Pad with NA or trim
Account for length change
Matrix dimension mismatch
Match vector to nrow or ncol
Check dim() first
Different group sizes
Use summary stats or tests
Don't compare element-wise
FAQ
Is vector recycling ever intentional?
Yes — recycling a scalar (length 1) is standard R: x * 2 or x + 1. Recycling with length matching the dimension (e.g., adding a 3-element vector to a 3-row matrix) is also intentional. The warning only fires when the lengths don't divide evenly.
Why does R recycle at all instead of just erroring?
Recycling is a core R design feature inherited from S. It enables concise vectorized code like x * 2 or matrix + row_vector. The trade-off is that it can silently produce wrong results when lengths are accidentally mismatched. Many R users consider the silent (no-warning) recycling case more dangerous.
What's Next?
R Error: argument is not a matrix — apply() on wrong object types
R Error: subscript out of bounds — indexing errors
R Common Errors — the full reference of 50 common errors