Search code examples
rgraphlabelreadabilityr-qgraph

Can qgraph render edge labels outside the actual edge?


I'm trying to insert edge labels outside the actual edge in my qgraph for readability purposes. I particularly don't like the option of include a white bg below the label, it screws up the edge. According to the manual, it is possible to adjust edge label position only along the line, but not on the side. Did anyone struggle with this before? Is it possible to circumvent this issue? Cheers


Solution

  • There does not seem to be a parameter for adjusting the across axis location of the edge label. One solution is to add the edge labels to the plot separately. An example is given below, which yielded the following plot. The general method is to obtain the layout of the plot, and then use the average of the two node locations to place the text along the line. There is a manual adjustment to the position so that the text will generally be parallel to the line, but mostly off the line (x and y offsets based on sine and cosine of angle). If you want further control you could manually adjust some of the text() locations for better results.

    enter image description here

    library(qgraph)
    
    # creating some random data
    set.seed(10)
    x1 <- rnorm(100,0,1)
    x2 <- x1 + rnorm(100,0,0.2)
    x3 <- x1 + x2 + rnorm(100,0,0.2)
    x4 <- rnorm(100,0,1)
    x5 <- x4 + rnorm(100,0,0.4)
    x6 <- x4 + rnorm(100,0,0.4)
    x7 <- x1 + x5 + rnorm(100,0,0.1)
    
    # making a data frame
    df <- cbind(x1,x2,x3,x4,x5,x6,x7)
    
    # calculating the qgraph for the correlation matrix
    # a stores the layout
    a <- qgraph(cor(df,method="pearson")
               ,layout="spring"
               ,label.cex=0.9
               ,labels=colnames(df)
               ,label.scale=F
               ,details=T
               ,edge.labels=T
               ,doNotPlot=T
               ,alpha=0.05
               ,minimum='sig'
               ,sampleSize=100)
    
    # plotting actual graph
    qgraph(cor(df,method="pearson")
           ,layout="spring"
           ,label.cex=0.9
           ,labels=colnames(df)
           ,label.scale=F
           ,details=T
           ,edge.labels=F
           ,doNotPlot=T
           ,alpha=0.05
           ,minimum='sig'
           ,sampleSize=100)
    
    # calculating significance
    pvalMat <- Hmisc::rcorr(df,type="pearson")
    
    # loop to add text
    for(i in 1:(nrow(a$layout)-1)){
      for(j in (i+1):nrow(a$layout)){
    
        # is correlation statistically significant
        if(pvalMat$P[i,j] < 0.05){
          # using stored layout values, col1 is x, col2 is y
          loc_center_x <- (a$layout[i,1]+a$layout[j,1])/2
          loc_center_y <- (a$layout[i,2]+a$layout[j,2])/2
    
          # finding angle of vector
          rotation <- atan((a$layout[i,2]-a$layout[j,2])/(a$layout[i,1]-a$layout[j,1]))*180/pi
    
          # radial separation
          radius <- 0.1
    
          # putting text at location
          text(labels=round(cor(df,method="pearson")[i,j],digits=2) # text of correlation with rounded digits
               ,x=loc_center_x + abs(radius*sin(rotation*pi/180))
               ,y=loc_center_y + abs(radius*cos(rotation*pi/180))
               ,srt=rotation
               ,adj=c(0.5,0.5)
               ,cex=0.8)
    
        }
      }
    }