1
votes

I have a question that probably has a simple answer, but I can't figure it out. I'm making a graphic using ggplot2, specifically geom_path(). The path is colored according to a categorical variable intersects, which takes the value TRUE if the path crosses a certain polygon and FALSE otherwise (I assigned group=1 so the paths are not grouped by the variable).

It is working almost as I would like it to, except that the color is applied to the following path segment instead of the preceding segment. For example, if observation i = TRUE, and i + 1 = FALSE, the resulting path is colored TRUE between positions i, i+1; and FALSE between positions i+1, i+2. I would like the path between positions i-1, i to be colored TRUE, and i, i+1 to be FALSE.

# Create polygon.
boundary_x <- c(640343.419, 640341.452, 640339.242, 640337.471, 640339.538, 640341.603)
boundary_y <- c(4858742.348, 4858733.404, 4858722.512, 4858722.853, 4858732.737, 4858742.649)
boundary <- data.frame(x = boundary_x, y = boundary_y)

# Sample data
x <- c(640338.007929366, 640338.077929366, 640338.857929366, 640338.867929366, 640338.459933366, 640338.407929366, 640338.174617366, 640338.139168366, 640338.070599366, 640337.747929366, 640337.847929366, 640338.439430366, 640338.777929366, 640338.877929366, 640339.444178366, 640339.557929366, 640340.247929366, 640340.927929366, 640340.977929366, 640341.107929366, 640341.157929366, 640341.427929366, 640341.477929366, 640341.807929366, 640341.847929366, 640342.427929366, 640342.642404366, 640342.867436366, 640342.878517366, 640343.116330366, 640343.097929366, 640343.007929366, 640342.387929366, 640341.929667366, 640341.837929366, 640339.927929366, 640339.847929366, 640336.427929366, 640335.717929366, 640335.057929366, 640334.967929366, 640334.681813366, 640334.208384366, 640334.172648366, 640334.417929366, 640334.587929366, 640334.777929366, 640334.987929366, 640334.925775366, 640338.257929366, 640338.187929366, 640338.057929366, 640338.077929366, 640338.077929366, 640340.200274366, 640341.037929366, 640341.114123366, 640341.187929366, 640341.237929366)
y <- c(4858731.28088173, 4858731.24088173, 4858730.80088173, 4858730.79088173, 4858728.57674273, 4858728.30088173, 4858727.05816773, 4858726.86768973, 4858726.36255673, 4858722.41088173, 4858722.03088173, 4858721.55321173, 4858721.29088173, 4858721.27088173, 4858721.16125073, 4858721.13088173, 4858721.06088173, 4858720.89088173, 4858720.90088173, 4858720.86088173, 4858720.85088173, 4858720.83088173, 4858720.84088173, 4858721.10088173, 4858721.14088173, 4858722.17088173, 4858722.50853873, 4858722.94242373, 4858722.98987973, 4858725.39572673, 4858725.44088173, 4858725.57088173, 4858725.69088173, 4858725.44266973, 4858725.40088173, 4858721.90088173, 4858721.81088173, 4858721.76088173, 4858721.93088173, 4858722.11088173, 4858722.18088173, 4858722.67533273, 4858723.32189973, 4858723.40558473, 4858727.23088173, 4858727.71088173, 4858728.14088173, 4858728.61088173, 4858730.42873273, 4858728.23088173, 4858727.62088173, 4858726.41088173, 4858726.32088173, 4858726.32088173, 4858726.02508273, 4858726.13088173, 4858726.13140073, 4858726.19088173, 4858726.23088173)
intersects <- c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE)
df <- data.frame(x = x, y = y, intersects = intersects)

# Plot
ggplot() + 
  geom_polygon(data = boundary, aes(x, y)) + 
  geom_path(data = df, aes(x, y, col = intersects, group = 1)) + 
  geom_point(data = df, aes(x, y, col = intersects)) + 
  coord_cartesian(xlim = c(640334, 640343), ylim = c(4858721, 4858731)) 

When you view the plot, you'll see the blue segments represent intersects = TRUE, and they occur right after the path crosses the polygon. I'd like to shift the color back, so to speak, so the segment actually crossing the polygon is colored.

I'm new around here and don't have enough reputation to post an image..sorry!

1
Please provide your code.Stéphane Laurent
Added some sample code.akdub

1 Answers

0
votes

The issue here is that you assign the colour (through the column intersects) to the points, not the lines that will actually carry the colour. ggplot2 considers each point to be the start of a line, which is then coloured, while you consider them to be the end of a line to be coloured.

You could, of course, just change your definition of the column intersection to go along with how ggplot2 handles the situation. Alternatively, you can modify the column when creating the plot using lead() from the dplyr package:

ggplot() + 
  geom_polygon(data = boundary, aes(x, y)) + 
  geom_path(data = df, aes(x, y, col = dplyr::lead(intersects, default = FALSE), group = 1)) + 
  geom_point(data = df, aes(x, y, col = intersects)) + 
  coord_cartesian(xlim = c(640334, 640343), ylim = c(4858721, 4858731)) +
  labs(col = "intersects")

enter image description here

The function lead() simply takes a vector and shifts its contents by one element to the left:

dplyr::lead(1:3)
## [1]  2  3 NA

Obviously, the function cannot know what to do with the last element of the vector, but you can provide the value that you want:

dplyr::lead(1:3, default = 7)
## [1] 2 3 7

There is also an analogous function dplyr::lag() that shifts in the other direction.