R Error in ggplot2: Aesthetics must be either length 1 or same as data
Error: Aesthetics must be either length 1 or the same as the data fires when a variable you map inside aes() has a different number of rows than the data frame ggplot2 is using. Below are the common causes and step-by-step fixes.
The Error
# This is what the error looks like:
# Error: Aesthetics must be either length 1 or the same as the data (20):
# colour
cat("This error means a vector in aes() doesn't match nrow(data).\n")
cat("ggplot2 can't recycle a vector of length 7 into 20 rows.\n")
The rule is simple: every aesthetic you pass inside aes() must have exactly 1 value (used for all rows) or the same number of values as rows in the data.
Cause 1: Mapping an External Vector Instead of a Column
The most common cause. You pass a standalone vector that happens to be a different length than your data frame:
df <- data.frame(x = 1:5, y = c(3, 7, 2, 9, 4))
my_colors <- c("red", "blue", "green") # length 3, but df has 5 rows
# This would error:
# library(ggplot2)
# ggplot(df, aes(x, y, color = my_colors))
# Fix: make the vector the same length as the data
my_colors_fixed <- c("red", "blue", "green", "red", "blue")
cat("Data rows:", nrow(df), "\n")
cat("Color vector length:", length(my_colors_fixed), "\n")
cat("Match:", nrow(df) == length(my_colors_fixed), "\n")
Fix: Add the vector as a column to the data frame first, then map that column.
Cause 2: Using a Summarized Variable with Raw Data
You compute a summary (e.g., a mean) and try to map it alongside the full data:
df <- data.frame(
group = rep(c("A", "B"), each = 5),
value = c(3, 5, 4, 6, 2, 8, 7, 9, 6, 10)
)
group_means <- tapply(df$value, df$group, mean)
cat("Data has", nrow(df), "rows\n")
cat("Means has", length(group_means), "values\n")
# Fix: merge summaries back into the original data
df$group_mean <- ave(df$value, df$group, FUN = mean)
cat("Now group_mean is length", length(df$group_mean), "- matches data\n")
print(head(df))
Fix: Use ave(), dplyr::left_join(), or merge() to attach summaries back to the original data before plotting.
Cause 3: Mismatched Data Sources Across Layers
Each ggplot layer can have its own data argument. If you map aesthetics that belong to one dataset inside a layer that uses another, lengths clash:
main_data <- data.frame(x = 1:10, y = rnorm(10))
annotations <- data.frame(x = c(3, 7), label = c("Peak", "Valley"))
cat("main_data:", nrow(main_data), "rows\n")
cat("annotations:", nrow(annotations), "rows\n")
# Fix: pass data explicitly to each layer
# ggplot(main_data, aes(x, y)) +
# geom_point() +
# geom_text(data = annotations, aes(x = x, y = 0, label = label))
cat("Each layer should reference its own data argument.\n")
Fix: Pass data = ... explicitly to the layer that uses a different data frame.
Cause 4: Factor Level Mismatch After Filtering
After subsetting data, leftover factor levels can cause subtle length mismatches in computed aesthetics:
df <- data.frame(
category = factor(c("A", "B", "C", "A", "B", "C")),
score = c(10, 20, 30, 15, 25, 35)
)
# Filter to just A and B
df_sub <- df[df$category %in% c("A", "B"), ]
cat("Rows:", nrow(df_sub), "\n")
cat("Factor levels still:", nlevels(df_sub$category), "(includes C)\n")
# Fix: drop unused levels
df_sub$category <- droplevels(df_sub$category)
cat("After droplevels:", nlevels(df_sub$category), "\n")
Fix: Use droplevels() after subsetting factor data.
Cause 5: Accidentally Passing a Data Frame Column from a Different Object
df1 <- data.frame(x = 1:5, y = 1:5)
df2 <- data.frame(x = 1:8, color_var = rep(c("A", "B"), 4))
# This would error because df2$color_var has 8 elements but df1 has 5 rows:
# ggplot(df1, aes(x, y, color = df2$color_var))
# Fix: only reference columns inside the data argument
cat("Rule: never use df2$col inside aes() when ggplot uses df1\n")
cat("Instead, join the data first or use the data argument per layer.\n")
Fix: Never reference another_df$column inside aes(). Join your data frames first.
Practice Exercise
# Exercise: This code will error. Fix it so the plot data is consistent.
scores <- data.frame(
student = paste("S", 1:6, sep = ""),
math = c(80, 90, 75, 88, 92, 70),
grade = c("A", "A", "B", "A", "A", "B")
)
highlight <- c(TRUE, FALSE, TRUE) # length 3, but 6 students
# Uncomment and fix:
# ggplot(scores, aes(student, math, fill = highlight)) + geom_col()
# Write your fix below:
Click to reveal solution
```r
scores <- data.frame(
student = paste("S", 1:6, sep = ""),
math = c(80, 90, 75, 88, 92, 70),
grade = c("A", "A", "B", "A", "A", "B")
)
# Fix: add highlight as a column with the correct length
scores$highlight <- c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE)
cat("Now scores has", nrow(scores), "rows and highlight has",
length(scores$highlight), "values\n")
# Now this would work:
# ggplot(scores, aes(student, math, fill = highlight)) + geom_col()
print(scores)
**Explanation:** The highlight vector had 3 elements for 6 rows of data. The fix is to make it length 6 and add it as a column to the data frame, then reference the column name in `aes()`.
Summary
Cause
Fix
Prevention
External vector wrong length
Add as column to data frame
Always map column names, not external vectors
Summary mixed with raw data
Use ave() or merge()
Compute summaries inside the data frame
Multiple data sources in layers
Pass data = per layer
Be explicit about which layer uses which data
Leftover factor levels
droplevels() after filtering
Drop unused levels after subsetting
Cross-referencing data frames
Join data first
Never use df2$col inside aes() of df1
FAQ
Can I use a single value in aes() without this error?
Yes. If you pass a length-1 vector, ggplot2 recycles it to match all rows. For example, aes(color = "red") works fine — but it maps a constant, so you likely want it outside aes() instead.
How do I debug which aesthetic is causing the problem?
The error message names the offending aesthetic (e.g., colour, size). Remove aesthetics one at a time until the plot renders, then check the length of the one that failed.
What's Next?
ggplot2 Error: object 'X' not found — data vs environment mapping issues
R Error: object 'x' not found — general object-not-found troubleshooting
R Common Errors — the full reference of 50 common errors