Search code examples
rggplot2aestheticsgeom-point

"Aesthetics must be either length 1" with different x, y and colour arguments


I have a problem that should be quite simple to fix but I haven't found any answers that are directly applicable to my situation.

I am trying to create a plot with geom_point in which the points shown are a filtered value from a character vector. y is a continuous numeric, x is a date and fill is a character vector.

Here's my sample data:

year    month   day attempt n_test
2019    6   22  1   NA
2019    7   13  2   n
2019    8   3   3   n
2019    8   20  4   n
2019    9   3   5   n
2019    9   4   6   n
2019    9   8   7   n
2019    9   11  8   p
2019    9   17  9   n
2019    10  3   10  n
2019    10  3   11  n
2019    10  11  12  c
2019    10  22  13  n
2019    10  25  14  n
2019    10  28  15  p
2019    11  6   16  c
2019    11  9   17  n
2019    11  25  18  n
2019    12  4   19  n
2019    12  8   20  n
2019    12  14  21  p
2019    12  17  22  n
2019    12  20  23  n

This is called 'ntest.csv'.

Here's my code:

ntest <- read.csv('ntest.csv', header = TRUE)
n_date <- ymd(paste(ntest$year, ntest$month, ntest$day, sep="-"))
ggplot(ntest, aes(n_date, y=attempt)) +
    geom_point(aes(colour = n_test), size = 3.5) +
    labs(x=NULL) +
    theme(legend.position="none",
          axis.text.x = element_text(color = "black", size = 10, angle=45),
          axis.text.y = element_text(color = "black", size = 10),
          axis.title.y = element_text(size = 13, vjust = 2)) +
    scale_x_date(date_breaks = "months" , date_labels = "%b-%y")

This gives the attached graph.

ntestplot

I want to only show the rows in my geom_point graph where n_test equals "p". So the same graph, with only the blue points. I've tried using

ntest %>% 
filter(n_test=="p")

before ggplot, but this results in:

"Error: Aesthetics must be either length 1 or the same as the data (3): x"

Any help would be greatly appreciated.


Solution

  • The problem here is that you are not making n_date part of your data frame, so it is not filtered when you filter the data frame and is thus a different length from it. The solution is simply to create it as a column in your data frame:

    ntest$n_date <- lubridate::ymd(paste(ntest$year, ntest$month, ntest$day, sep="-"))
    

    Now you can apply your filter and your plot will work (note that the points are red because there is now only one colour group):

    ggplot(ntest %>% filter(n_test == "p"), aes(n_date, y=attempt)) +
        geom_point(aes(colour = n_test), size = 3.5) +
        labs(x=NULL) +
        theme(legend.position="none",
              axis.text.x = element_text(color = "black", size = 10, angle=45),
              axis.text.y = element_text(color = "black", size = 10),
              axis.title.y = element_text(size = 13, vjust = 2)) +
        scale_x_date(date_breaks = "months" , date_labels = "%b-%y")
    

    enter image description here