9

What I am trying to accomplish: manually add shapes (lines and circles for a soccer pitch, in my actual project) to a scatterplot. This is a scaled-down example of my actual project, but illustrates the issue I need help with.

Here is the data I am using for this example:

data <- data.frame("name" = c("A", "A", "B", "B", "C", "C"),
                     "x" = c(.13, .64, .82, .39, .51, .03),
                     "y" = c(.62, .94, .10, .24, .20, .84))

I will provide example code, first one way that works (tedious, too long), and then one way that I can't figure out (which seems more efficient/concise, and possilbly... faster?).

library(ggplot2)

ggplot(data, aes(x, y)) +
  geom_point() +
  geom_segment(aes(x = 0,xend = 1,y = 1,yend = 1)) +
  geom_segment(aes(x = 0, xend = 1, y=0,yend=0)) +
  geom_segment(aes(x=1, xend=1, y=0, yend=1)) +
  geom_segment(aes(x=0, xend=0, y=0, yend=1))

Example plot of player position on 1x1 soccer pitch

This gets me a nice 1x1 pitch with 6 data points (don't think I can embed the plot, since I don't have enough reputation). Since my actual project has many more data points, and also many more "shapes" (line segments, circles, and circle arcs) that make up the pitch, I thought it would be better to use vectors to define the geom_segment aesthetics - since the full data set plots very slowly. This is what I have:

ggplot(data, aes(x, y)) +
  geom_point() +
  geom_segment(aes(x = c(0,0,1,0),
               xend = c(1,1,1,0),
               y = c(1,0,0,0),
               yend = c(1,0,1,1)))

I get the following error:

Error: Aesthetics must be either length 1 or the same as the data (16): x, y, xend, yend

I have tried changing the layer where I call aes(), using the inherit.aes = FALSE in geom_segment, but it still gives that error. I'm relatively new to R, and very new to SO, so my apologies if I'm using any incorrect terminology or protocol when posting this question.

The issue is that when listing out each of the shapes that make up the pitch individually (an extra layer for every single line segment or circle), and then adding the x, y data as points, it takes forever for the plot to render.

Any help avoiding that error when using vectors to plot the shape layers, or any other creative solutions would be great. My main goal is to make this plot of many shapes and many data points render more quickly (having more elegant code would be a nice bonus as well).

Thank you!

6
  • 5
    Perhaps this package can help? github.com/Torvaney/ggsoccer Commented Aug 29, 2018 at 6:00
  • 4
    geom_segment will only take single data entries if you give them like that. Instead, put them in a data.frame and pass the data.frame to geom_segment. Make sure your aes maps the correct columns to x y xend and yend. This should indeed make things at least a little faster, and your code a bit more straightforward. Good luck. (Thanks for a very clear question!) Commented Aug 29, 2018 at 6:10
  • @Axeman - thank you. So you mean just put all 4 vectors (x, xend, y, yend) into one df then pass the df object into geom_segment(aes(df)) ? Commented Aug 29, 2018 at 6:31
  • 2
    Please study the first example in ?geom_segment. Also read ?ggplot. Commented Aug 29, 2018 at 6:36
  • 1
    No, each geom has a data argument. That is where the data.frame goes. Aes refers to the column in that data. Commented Aug 29, 2018 at 6:37

1 Answer 1

8

What Axeman is trying to say is, write and extra data frame with your segments and load this into the geom_segment function via the data parameter. If you do so, it doesn't use the standard data provided to the ggplot function but it will use it's own data.

Something like

data <- data.frame("name" = c("A", "A", "B", "B", "C", "C"),
                   "x" = c(.13, .64, .82, .39, .51, .03),
                   "y" = c(.62, .94, .10, .24, .20, .84))

seg_df <- data.frame(x=c(0,0,1,0),
                     y=c(1,0,0,0),
                     xend=c(1,1,1,0),
                     yend=c(1,0,1,1))

ggplot(data, aes(x, y)) +
  geom_point() +
  geom_segment(data=seg_df, aes(x, y, xend=xend, yend=yend))
Sign up to request clarification or add additional context in comments.

3 Comments

You guys are awesome. Thank you for the help, and clear explanations.
@ForceLeft415 feel free to mark this question as solved if my answer helped.
You got it! Sorry, still getting down SO etiquette.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.