Error: object 'i' not found in geom_hline and geom_vline

96 Views Asked by At

I want to make a scatter plot with a horizontal and a vertical line. The lines shall appear at the mean of the x and y variable. What I do is:

# Some data
df <- data.frame(x= rnorm(100), y= rnorm(100))
df$i1 <- mean(df$x)
df$i2 <- mean(df$y)

# Plot
library(ggplot2)    
ggplot(data= df, mapping= aes(x= x, y= y)) +
  geom_point() +
  geom_vline(xintercept= unique(i1)) +
  geom_hline(yintercept= unique(i2))

I expect to see a scatter plot with a horizontal line a the mean of y and a vertical line at the mean of x. Instead I get the error Error: object 'i1' not found.

I want to use the values straight from the column of the data argument (here the variables df$i1 and df$i2), i.e. I do not want to put in the intercept values manually and I want to avoid to create a new dataframe containing only the intercepts. Is this possible?

EDIT

In fact my situation includes a grouping variable which I left out for simplicity in the original question. This led to some confusion. The actual data is actually something like this:

Group data:
library(tidyverse)
df <- data.frame(x= rnorm(100), y= rnorm(100), group= sample(1:2, 100, TRUE)) %>%
  group_by(group) %>%
  mutate(i1= mean(x),
         i2= mean(y))

As pointed out in the answer the grouping variable is not relevant to the question and can be simply added later with facet_wrap.

2

There are 2 best solutions below

3
On

Based on the original question, the issue was with precomputing the means.

ggplot(df, aes(x = x, y= y)) +
  geom_point() +
  geom_vline(aes(xintercept = mean(x))) +
  geom_hline(aes(yintercept = mean(y)))

plot with hline and vline

Base R solution for grouped data:

# Some data
set.seed(2023)
df <- data.frame(x = rnorm(100), 
                 y = rnorm(100),
                 group = sample(1:2, 100, TRUE))



ggplot(df, aes(x = x, y = y)) +
  geom_point() +
  geom_vline(data = data.frame(xintercept = aggregate(df$x, list(df$group), FUN = mean)$x),
             aes(xintercept = xintercept)) +
  geom_hline(data = data.frame(yintercept = aggregate(df$y, list(df$group), FUN = mean)$x),
             aes(yintercept = yintercept))

gives: enter image description here

0
On

The code inside geom_hline and geom_vline must be wrapped into aes, i.e:

# For data without groups:
df <- data.frame(x= rnorm(100), y= rnorm(100))
df$i1 <- mean(df$x)
df$i2 <- mean(df$y)

# Plot
library(ggplot2)    
ggplot(data= df, mapping= aes(x= x, y= y)) +
  geom_point() +
  geom_vline(aes(xintercept= i1)) +
  geom_hline(aes(yintercept= i2))

The code for data with groups is the same (so groups do not matter in the question and can be added later). The code is then:

# Group data:
library(tidyverse)
df <- data.frame(x= rnorm(100), y= rnorm(100), group= sample(1:2, 100, TRUE)) %>%
  group_by(group) %>%
  mutate(i1= mean(x),
         i2= mean(y))

# Same code..
    library(ggplot2)    
ggplot(data= df, mapping= aes(x= x, y= y)) +
  geom_point() +
  geom_vline(aes(xintercept= i1)) +
  geom_hline(aes(yintercept= i2)) +
  facet_wrap(. ~ group) # Just add the grouping variable