2

I am working on 3-way interaction effect plotting using my own data. But my code creates too many (continuous) shapes along the lines.

Attached please see my figure I got.

How can I leave the points only at the ends of the lines instead of the figure attached above?

I will deeply appreciate if anybody helps.

    g1=ggplot(mygrid,aes(x=control,y=pred,color=factor(nknowledge),
                 lty=factor(nknowledge),shape=factor(nknowledge)))+
    geom_line(size=1.5)+
    geom_point(size=2.5)+
    labs(x="control", y="attitudes",lty = "inc level")+
    scale_linetype_manual("know level",breaks=1:3,values=c("longdash", "dotted","solid"),label=c("M-SD","M","M+SD"))+
    scale_color_manual("know level",breaks=1:3,values=c("red", "blue","grey"),label=c("M-SD","M","M+SD"))+
    scale_shape_manual("know level",breaks=1:3,values=c(6,5,4),label=c("M-SD","M","M+SD"))+
    theme_classic()
Kate Jang
  • 21
  • 2
  • It's easier to help you if you include a simple [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input that can be used to test and verify possible solutions. – MrFlick Jan 29 '21 at 05:16

2 Answers2

2

This could be achieved by making use of a second dataset which filters the data for the endpoints by group using e.g. a group_by and range and passing the filtered dataset as data to geom_point:

Using some random example data try this:

set.seed(42)

mygrid <- data.frame(
  control = runif(30, 1, 7),
  pred = runif(30, 1, 3),
  nknowledge = sample(1:3, 30, replace = TRUE)
)

library(ggplot2)
library(dplyr)

mygrid_pt <- mygrid %>% 
  group_by(nknowledge) %>% 
  filter(control %in% range(control))

ggplot(mygrid,aes(x=control,y=pred,color=factor(nknowledge),
                     lty=factor(nknowledge),shape=factor(nknowledge)))+
  geom_line(size=1.5)+
  geom_point(data = mygrid_pt, size=2.5)+
  labs(x="control", y="attitudes",lty = "inc level")+
  scale_linetype_manual("know level",breaks=1:3,values=c("longdash", "dotted","solid"),label=c("M-SD","M","M+SD"))+
  scale_color_manual("know level",breaks=1:3,values=c("red", "blue","grey"),label=c("M-SD","M","M+SD"))+
  scale_shape_manual("know level",breaks=1:3,values=c(6,5,4),label=c("M-SD","M","M+SD"))+
  theme_classic()

stefan
  • 90,330
  • 6
  • 25
  • 51
  • 2
    Thank you very much Stefan. I applied the code you created and it worked perfectly. I deeply appreciated! – Kate Jang Jan 30 '21 at 08:09
1

If you use geom_point, then you'll get points for all rows in your data frame. If you want specific points and shapes plotted at the ends of your lines, you'll want to create a filtered data frame for the only points you want to have plotted.

library(ggplot2); library(dplyr)
g1 <- ggplot()+
  geom_line(data = mtcars,
            mapping = aes(x=hp,y=mpg,color=factor(cyl),lty=factor(cyl)),
            size=1.5)+
  geom_point(data = mtcars %>% group_by(cyl) %>% filter(hp == max(hp) | hp == min(hp)),
             mapping = aes(x=hp,y=mpg,color=factor(cyl),shape=factor(cyl)),
             size=2.5)
g1

Created on 2021-01-28 by the reprex package (v0.3.0)

Arthur Yip
  • 5,810
  • 2
  • 31
  • 50
  • 2
    Thank you very much Arthur. I applied the code you created and I could get the figure I wanted. Thanks a lot for your help :) – Kate Jang Jan 30 '21 at 08:08