# project.point

project.point is a helper function. In many graphics in Schoon, Melamed, and Breiger (2024) and those generated by rio.plot, the points for predictor variables are projected to the line running through the origin (0,0) and the fitted values from the regression model. Given the point coordinates for the point you want to project onto that line, and the coordinates for the fitted values, project.point computes the point at which your point is projected onto the line - at a 90 degree angle - running through the origin (0,0) and the fitted values. You can then connect those points in graphs using a line segment. See below for an example.

We begin this example by defining a rio.plot with all the predictor variables suppressed. We will add them, using project.point in the process.

    library(rioplot)
    data(Kenworthy99)
    m1 <- lm(scale(dv) ~ scale(gdp) + scale(pov) + scale(tran) -1,data=Kenworthy99)
    # Create plot with just the fitted values
    rp1 <- rio.plot(m1,include.int="no",exclude.vars=1:3,col.names = "PRED.POV")
    rp1$gg.obj

In order to add the predictor or independent variables to the plot, we need their coordinates. Below we define a second rio.plot object, and then build a data.frame with the coordinates for the variables (or columns). We then print the data.frame to show the coordinates. Finally, we use those coordinates to add the points to the rio.plot$gg.obj. Next, we will use project.point to connect the points for the variables to the rio.plot line.

    # Create object with coordinates for all variables
    rp2 <- rio.plot(m1,include.int="no")
    # pull out those coordinates and put them into a data.frame
    pdat <- data.frame(vars=c("gdp","prepov","tran","yhat"),
                       x=rp2$col.dimensions[,1],y=rp2$col.dimensions[,2])
    pdat

    ##     vars          x          y
    ## 1    gdp -0.4978672  0.3622994
    ## 2 prepov  0.6609921  0.1332760
    ## 3   tran  0.1532521 -0.8283859
    ## 4   yhat  0.5401217  0.4058982

    rp1$gg.obj +
      scale_x_continuous(limits=c(-.6,1.15)) +
      scale_y_continuous(limits=c(-.85,.5)) +
      geom_point(data=pdat[1:3,],aes(x=x,y=y)) +
      geom_text(data=pdat[1:3,],aes(x=x,y=y,label=vars),nudge_y=.1,nudge_x=.1)

project.point computes the point at which your point is projected onto the line - at a 90 degree angle - running through the origin (0,0) and the fitted values. In the first example below, project.point computes the point at which gdp is projected onto the line. We then define three objects - one for each predictor variable. We then compile the new points with the coordinates for the predictors, along with a grouping variable that defines the line segments. Finally, we use these new data to connect the points for the predctors to the rio.plot line.

    project.point(pdat[1,2:3],pdat[4,2:3]) # gdp

    ## $newpoint
    ## $newpoint$y
    ## [1] -0.1441779
    ##
    ## $newpoint$y
    ## [1] -0.1083488

    # points for each predictor
    a1<-project.point(pdat[1,2:3],pdat[4,2:3])$newpoint # gdp
    a2<-project.point(pdat[2,2:3],pdat[4,2:3])$newpoint # prepov
    a3<-project.point(pdat[3,2:3],pdat[4,2:3])$newpoint # tran
    # compile those points into a data.frame
    p1 <- data.frame(x=as.numeric(a1[1]),y=as.numeric(a1[2]),gr=1)
    # output from project.point
    p2 <- data.frame(pdat[1,2:3],gr=1) # gdp's coordinates
    p3 <- data.frame(x=as.numeric(a2[1]),y=as.numeric(a2[2]),gr=2)
    # output from project.point
    p4 <- data.frame(pdat[2,2:3],gr=2) # prepov's coordinates
    p5 <- data.frame(x=as.numeric(a3[1]),y=as.numeric(a3[2]),gr=3)
    # output from project.point
    p6 <- data.frame(pdat[3,2:3],gr=3) # tran's coordinates
    pdat2 <- rbind(p1,p2,p3,p4,p5,p6)
    pdat2

    ##             x          y gr
    ## 1  -0.1441779 -0.1083488  1
    ## 2  -0.4978672  0.3622994  1
    ## 3   0.4864365  0.3655541  2
    ## 21  0.6609921  0.1332760  2
    ## 11 -0.2999054 -0.2253771  3
    ## 31  0.1532521 -0.8283859  3

    # the groups denote the two points that define the beginning and
    # end of the line segments.
    rp1$gg.obj +
      scale_x_continuous(limits=c(-.6,1.15)) +
      scale_y_continuous(limits=c(-.85,.5)) +
      geom_line(data=pdat2,aes(x=x,y=y,group=gr),color="grey65") +
      # line segments from project.point
      geom_point(data=pdat[1:3,],aes(x=x,y=y)) +
      geom_text(data=pdat[1:3,],aes(x=x,y=y,label=vars),nudge_y=.1,nudge_x=.1)