Home > other >  ggplot2 geom_path plot is very "fuzzy." How can I fix this?
ggplot2 geom_path plot is very "fuzzy." How can I fix this?

Time:01-15

I am seeing some very strange (and undesirable) behavior from ggplot. I am using the following code to generate a plot with differently colored segments along a single path.

library(data.table)
library(ggplot2)

testData = fread("test_data.tsv")

ggplot(testData, aes(X, Y, color = Color, group = 1))  
  geom_path(size = 1.5)   scale_color_identity()

(The data within "test_data.tsv" can be found at fuzzy plot

As you can see, the edges are VERY fuzzy (or blurry, or jagged, or whatever you want to call them), and I can't seem to fix them. I've tried exporting at a higher dpi, or in other graphics formats, such as pdf, but nothing has worked.

Interestingly enough, zooming in on the blurry sections seems to give some insight into what is happening: fuzzy zoom

Each point appears to be aligned to connect to its neighbors, but the actual joining isn't going smoothly at all. I assume this is an artifact of using the "group = 1" parameter to prevent ggplot from connecting all of the like-colored regions together. However, I can't change that option for exactly that reason.

Is there a workaround to this issue that I could implement, or am I just running up against limitations of ggplot at this point?

CodePudding user response:

This has to do with having so many data points and a (relatively) thick line - so no issue with your plot code. If you check your data using a smaller value for size, you don't get the "fuzzy" look, but it's harder to visualize the thin line:

ggplot(testData, aes(X, Y, color = Color, group=1))  
  geom_path(size=0.5)   scale_color_identity()

enter image description here

The fix is to use the lineend=... argument in geom_path() to smooth out the places where the points are joined. This does not have much effect at all until the line size is set to be pretty large (say, larger than 1). The default value is lineend="butt" which draws a hard edge ending right at the point. The option you want to use here is lineend="round" which gives a rounded edge. Here's what it looks like:

ggplot(testData, aes(X, Y, color = Color, group=1))  
  geom_path(size=1.5, lineend = "round")   scale_color_identity()

enter image description here

Detailed view of how it's working

To get a better idea why this works, let's take an example dataset shown below. First, here's the plot when the default value is used (lineend="butt"):

set.seed(8675309)
df <- data.frame(x=1:20, y=sample(-50:50, size=20, replace=T), col = sample(LETTERS[1:2], size=20, replace=T))

ggplot(df, aes(x,y, color=col, group=1))  
  geom_path(size=5, lineend="butt", alpha=0.8, show.legend = FALSE)  
  theme_light()

enter image description here

Now here's the difference when you set lineend="round":

ggplot(df, aes(x,y, color=col, group=1))  
  geom_path(size=5, lineend="round", alpha=0.8, show.legend = FALSE)  
  theme_light()

enter image description here

  •  Tags:  
  • Related