Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
804 views
in Technique[技术] by (71.8m points)

r - Adding Slight curve (or bend) in ggplot geom_path to make path easier to read

This question is a new question from a previously answered question located here: Plot mean of data within same ggplot

As you can see in the .jpg picture below-- the red line geom_path gets squeezed together making the line harder to interpret. Is there a way to "bend" the curve slightly so that there is less overlap / bunching? Some kind of smoothing or bending around the points so the lines don't overlap? Red-line geom_paths are squeezed together

Here is my syntax:

orbit.plot <- ggplot(orbit.data, aes(x=OpM, y=INVT, colour=Subj, label=Year)) +
  geom_point(size=7, shape=20) + 
  geom_path(size=1.5) +
  ggtitle("Title Orbits") +
  geom_text(data=subset(orbit.data,Year==2006 | Year==2014), aes(label=Year, vjust=1, hjust=1)) +
  theme(panel.background = element_rect(fill = 'white', colour = 'red'),  
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank()) +
  geom_vline(xintercept=0, size=1) +
  geom_hline(yintercept=7, size=1) +
  scale_y_continuous(limits = c(7, 15), breaks=seq(7,15,1/2))

Here is dput of the data set:

structure(list(Year = c(2006L, 2006L, 2007L, 2007L, 2008L, 2008L, 
2009L, 2009L, 2010L, 2010L, 2011L, 2011L, 2012L, 2012L, 2013L, 
2013L, 2014L, 2014L), Subj = structure(c(2L, 1L, 2L, 1L, 2L, 
1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L), .Label = c("TMC", 
"HMC"), class = "factor"), OPM = c(0.088, 0.09, 0.095, 0.078, 
0.085, 0.08, -0.023, 0.019, 0.009, 0.043, 0.025, 0.065, 0.0199, 
0.029, 0.06, 0.055, 0.088, 0.065), Invt = c(14.5, 10.3, 13.8, 
10, 13.3, 9.5, 12.3, 8, 13.5, 8, 14.3, 10, 13.2, 8.5, 13.8, 9.5, 
13.8, 9.75)), .Names = c("Year", "Subj", "OpM", "INVT"
), class = "data.frame", row.names = c(NA, -18L))

Thank you kindly.

EDIT: UPDATE: Essentially, the reason for this plot is to show x/y variable "motion" over time. On the X axis-- I'm plotting a ratio (operating margin in this case). On the Y-axis-- I'm showing a cycle measure (inventory turns in this case.) The "bending" of the curve will certainly "bend" the data itself-- but with the X/Y measures I'm using, the data is understood to two (2) decimals-- so "slight" bending of the data would not contaminate the "essence" of what the data is trying to portray.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could spline it:

library(ggplot2)
orbit.data <- structure(list(Year = 
   c(2006L, 2006L, 2007L, 2007L, 2008L, 2008L,  2009L, 2009L,  2010L, 2010L, 
     2011L, 2011L, 2012L, 2012L, 2013L,  2013L, 2014L, 2014L), 
   Subj = structure(c(2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 
                      2L, 1L, 2L, 1L, 2L, 1L), 
          .Label = c("TMC", "HMC"), class = "factor"), 
   OPM = c(0.088, 0.09, 0.095, 0.078,  0.085, 0.08, -0.023, 0.019, 0.009, 
           0.043, 0.025, 0.065, 0.0199, 0.029, 0.06, 0.055, 0.088, 0.065), 
   Invt = c(14.5, 10.3, 13.8, 10, 13.3, 9.5, 12.3, 8, 13.5, 8, 14.3, 
            10, 13.2, 8.5, 13.8, 9.5, 13.8, 9.75)), 
   .Names = c("Year", "Subj", "OpM", "INVT"), class = "data.frame", 
   row.names = c(NA, -18L))

lsdf <- list()
plot.new()
for (f in unique(orbit.data$Subj)){
  psdf <- orbit.data[orbit.data$Subj==f,]
  newf <- sprintf("%s - xspline",f)
  lsdf[[f]] <- data.frame(xspline(psdf[,c(3:4)], shape=-0.6, draw=F),Subj=newf)
}
sdf <- do.call(rbind,lsdf)   
orbit.plot <- ggplot(orbit.data, aes(x=OpM, y=INVT, colour=Subj, label=Year)) +
  geom_point(size=5, shape=20) + 
  geom_point(data=orbit.data,size=7, shape=20,color="black") + 
  geom_path(size=1) +
  geom_path(data=sdf,aes(x=x,y=y,label="",color=Subj),size=1) + 
  ggtitle("Title Orbits") +
  geom_text(data=subset(orbit.data,Year==2006 | Year==2014), 
             aes(label=Year, vjust=1, hjust=1)) +
  theme(panel.background = element_rect(fill = 'white', colour = 'red'),  
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank()) +
  geom_vline(xintercept=0, size=1) +
  geom_hline(yintercept=7, size=1) +
  scale_y_continuous(limits = c(7, 15), breaks=seq(7,15,1/2))
print(orbit.plot)

Which gives:

enter image description here

There are lots of ways to do this, I doubt this is the best. You can play with the shape parameter in the xspline call to get different amounts of curvature.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...